members

members

【2020年版】Git Push(git-ftp)でWebサーバーにFTPアップロード(Windows/SourceTreeユーザー向け)

Tweet


画像:PhotoFunia

git-ftpは、Gitの更新差分のみをFTPでアップロードできるGitのサブコマンドです。git-ftpをGitのフックとして設定すれば、Git Pushと連動してのFTPアップロードが可能なため、Webサイト構築の際によく利用されます。
しかしgit-ftpは導入の際にハマるポイントが多く、特にコマンド操作に慣れていない方などにとっては解決が難しいため、導入をあきらめてしまう方も多いのではないでしょうか。
そこで今回は、SourceTreeで開発しているWindowsユーザー向けに、既にあるGitリポジトリにgit-ftpを導入する際の手順をハマりやすいポイントを押さえながら紹介します。最後にはよくあるエラーメッセージとその対処方法について、具体的に説明します。

 

導入手順

git-ftpの導入手順は大きく次の通りです。1つずつ手順を説明していきます。

  1. Gitをインストールする(Chocolateyでインストール)
  2. git-ftpをインストールする
  3. curlをインストールする(※Git for Windows v2.25.1 以上ではこの手順は不要になりました)
  4. Gitリポジトリにgit-ftpを導入する

 

導入手順1. Gitのインストール(Chocolateyでインストール)

まず、コマンドやアプリを簡単にインストールできるパッケージ管理システムであるChocolateyをインストールします※。

※Windowsのパッケージ管理システムで他に有名なものとしてはscoopがありますが、Gitのインストールパスがユーザー毎となり、Visual Studio CodeでGitを利用する際などに、ひと手間必要になってしまうため、本稿ではChocolateyを利用します。

[Windowsキー]を押しながら[Xキー]を押してから一度キーを離した後、[Aキー]を押して、PowerShellのターミナル(以後「青い画面」と記載)を管理者権限で起動します。起動したら、リスト1のコマンドをコピー&ペーストした後、[Enterキー]を押してください(ペーストは青い画面で[Shiftキー]を押しながら[Insertキー]を押すか、マウスを右クリックすることでできます)(図1参照)。

図1. PowerShellの起動とChocolateyのインストール

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

リスト1

ペースト後、[Enterキー] を押すと、Chocolateyのインストールが行われます。
Chocolateyのインストールが完了したら、今度はGit fo Windowsのインストールを行います。同じ青い画面で、リスト2の内容を入力してインストールしてください(このGitを一般的に「システムにインストールしたGit」または単に「システムのGit」と呼びます)。

cinst -y git

リスト2

 

導入手順2. git-ftpのインストール

ここで1つ目のハマリポイントです。最初に説明したとおり、git-ftpはGitのサブコマンドのため、今回利用するシステムのGitが参照できる場所にインストールする必要がありますが、SourceTreeを利用している場合は注意が必要です。 SourceTreeはGitを内蔵しており、設定画面から、システムにインストールしたGitを使用するか、内蔵のGitを使用するかを選択することができます。 この「どのGitを使用するか」の設定を確認せずにgit-ftpを導入すると、例えば『Visual Studio Codeからpushした場合にはgit-ftpが動作するのに、SourceTreeからpushした場合に動作しない…』ということになってしまいます。 SourceTreeのバージョンによっては、この設定が異なる場合があるので、次の手順で説明するSourceTreeの設定画面から確認が必要です。SourceTreeに内蔵のGitは、SourceTreeをアンインストールすると削除されてしまうため、本稿ではシステムのGitを利用する手順を説明します。

SourceTreeを起動し、メニューから「ツール」→「オプション」をクリックしてオプション設定画面を開きます。「Git」タブをクリックして一番下にスクロールすると、「 Git バージョン」という領域に「System」ボタンがあり、その下に現在選択中のGitの種類が記載されています(図2参照)。もし「内蔵 Git バージョン x.xx …」となっている場合、「System」ボタンをクリックし、システムのGitを使用するように変更します。

図2. SourceTreeで現在選択中のGitの種類

ここまでの確認が終わったら、git-ftpをインストールします。
[Windowsキー]を押したあと「git bash」と入力し、Gitのターミナル(Gitをコマンドで操作するための環境)である「Git Bash」を起動します。
Git Bashでリスト3の内容を入力し、git-ftpの公式ドキュメントの手順通りにgit-ftpをインストールしていきます。

curl https://raw.githubusercontent.com/git-ftp/git-ftp/master/git-ftp > /bin/git-ftp
chmod 755 /bin/git-ftp

リスト3

 

導入手順3. curlのインストール

※【2020/3/15追記】 Git for Windows v2.25.1 以上に同梱のcurlはSFTPプロトコルをサポートするようになったため、「導入手順3. curlのインストール」の手順が不要になりました。 諸事情でGitのバージョンをv2.25.1 以上に上げられない場合にのみ、この手順を実施してください。

ここで2つ目のハマリポイントがあります。git-ftpはcurl(カール)というコマンドの機能を利用しています。このcurlは、WindowsやシステムのGit Bashにも付属していますが、これらに付属しているcurlはSFTPプロトコルに対応していません(※)。青い画面でリスト4の内容を入力して、SFTPに対応したcurlをインストールします。

cinst -y curl

リスト4

ここで早くも3つ目のハマリポイントです。 SFTPに対応したcurlをインストールしただけでは、まだGit Bashに付属のcurlが使用される状態のままです。 この場合、通常はシステム環境変数PATHの順番を変更する必要がありますが、システム環境変数PATHの順番を変えることによる影響を考慮し、本稿ではGit Bashの中でのみ環境変数PATHを書き換え、SFTPに対応したcurlの優先順位を上げる方法で対処します。
Git Bashの設定ファイルである .bash_profile の中で、環境変数PATHを書き換えます。お好みのエディタでホームディレクトリ(C:\Users\【ユーザー名】)配下にある、.bash_profileを開き、リスト5の内容を追加します。
(※SFTP_CURL_PATHには、SFTPに対応したcurlのパス(と区切り文字の : )を指定します。リスト5ではChocolateyでcurlをインストールした際のパスを記載しています)

SFTP_CURL_PATH="/c/ProgramData/chocolatey/bin:"
export PATH=$SFTP_CURL_PATH$(echo $PATH | sed "s|$SFTP_CURL_PATH||")

リスト5 ~/.bash_profile

 

導入手順4. Gitリポジトリにgit-ftpを導入する

git-ftpは次のような手順で導入します。

  • 1) git-ftpとgit pushのフックを設定するための初期設定スクリプトを用意する
  • 2) git-ftpの初期設定を行う

 

1) git-ftpとgit pushのフックを設定するためのスクリプトを用意する

リスト6に弊社でよく利用する初期設定スクリプトを示します。このスクリプトを導入すると、developブランチでgit pushを行うと、連動して対応するSFTPサーバーにアップロードを行ってくれるようになります。
①~④でftpサーバーの情報(①ホスト名、②ドキュメントルートのパス、③SFTPのユーザー名、④SFTPのパスワード)を入力して、git-ftp対応したいGitリポジトリ(本稿では、/c/develop/test_repo/ にGit Clone済みの場合の例を記載します)に「gitsetup.sh」等の名前で保存し、Git管理の対象としてコミットします。

ここでのハマりやすいポイントとしては、②はSFTPログインしたときに見えるドキュメントルートのパスという点です。WebサーバーのURLとは違う点に注意してください。

#!/bin/sh
# git-ftpがインストールされていなければインストール
which git-ftp
if [ "$?" -eq 1 ]; then
  curl https://raw.githubusercontent.com/git-ftp/git-ftp/master/git-ftp > /bin/git-ftp
  chmod 755 /bin/git-ftp
fi

# ftp情報
git config git-ftp.url 'sftp://【①SFTPサーバーのホスト名】/【②SFTPログインした際のドキュメントルートのパス】'
git config git-ftp.user xxx # …③SFTPのユーザー名
git config git-ftp.password xxx # …④パスワード
git config git-ftp.insecure 1
# ⑤ 複数のプロジェクトで同じFTPサーバー且つおなじパスを使用せざるを得ない場合は
# git-ftp.deployedsha1fileで、別のログファイル名を設定する。
# git config git-ftp.deployedsha1file .git-ftp-xxx.log

[ -e .git/hooks/pre-push ] && mv .git/hooks/pre-push .git/hooks/pre-push.bak

# git pushフックの設定 …⑥
cat << '__EOF' > .git/hooks/pre-push
#!/bin/sh
# Git for Windows v2.25.1 以上を導入していない場合は、
# ~/.bash_profileで環境変数PATHにSFTPプロトコルに対応したcurlのパスを設定してください。
# source ~/.bash_profile
while read local_ref local_sha1 remote_ref remote_sha1
do
  if [[ "${remote_ref##refs/heads/}" = "develop" ]]; then
    exec git ftp push
    exit 0
  fi
done
__EOF

リスト6 /c/develop/test_repo/gitsetup.sh

コミットしたら、Git bashを起動し、gitsetup.shを実行します(リスト7)。

cd 【ローカルのGitリポジトリのパス】
./gitsetup.sh

リスト7

この gitsetup.sh は、対象のGitリポジトリで開発を行うメンバー全員に、1回だけ実行してもらう必要があります。

 

2) git-ftpの初期設定を行う

git-ftpは、ftpサーバーに.git-ftp.logという名前で、最後にアップロードしたコミットハッシュを記録しています。これによりgit-ftpは差分のみをアップロードすることが可能になっています。
このためgit-ftpを導入する場合は、初回の1回のみ、ftpサーバーに.git-ftp.logを作成する作業を行う必要があります。
Git bashを起動し、git ftp init を実行します(リスト8)。

cd 【ローカルのGitリポジトリのパス】
git ftp init

リスト8

ここでもハマりやすいポイントがあります。1)の②のディレクトリが空でない場合に、以下のようなエラーが出力される場合があります(リスト9)。

curl: (23) Failed writing body (0 != 58)
2019年 3月 19日 火曜日 22:46:21    : fatal: Can't access remote 'sftp://xxx:***@xxx.com', exiting...

リスト9

この場合は、リスト10の内容を入力することで、.git-ftp.logファイルが生成されます。

git ftp catchup

リスト10

以上で、初期設定は終わりです。

 

よくあるエラーと対処方法

次によくあるエラーとその具体的な対処方法を説明します。

■エラ-その1:git ftp initや、git ftp push をしようとしたが、リスト11のようなエラーメッセージが出力される。

fatal: Dirty repository: Having uncommitted changes. Exiting...

リスト11

原因と対処方法1: git-ftpはcommitしていない変更があると、動作しないという制約があります。 まずファイルの変更をcommitしてください。

 

■エラ-その2:リスト12のようなエラーメッセージが出力される。

fatal: Remote host not set.

リスト12

原因と対処方法2: git-ftpの設定が読み込まれていません、リスト7の手順で、gitsetup.shを実行してください。

 

■エラ-その3: gitsetup.shを修正したが、修正した内容が反映されない。

原因と対処方法3: gitsetup.shを修正しただけでは、設定が反映されません。 リスト7の手順で、gitsetup.shを実行し直してください。

 

■エラ-その4:リスト13のようなエラーメッセージが出力される。

fatal: Protocol 'sftp' not supported by curl, exiting...

リスト13

原因と対処方法4: SFTPプロトコルをサポートしていないcurlが使用されています。 Gitのバージョンを v2.25.1 以上にあげるか、「導入手順3. curlのインストール」で、SFTPプロトコルをサポートしたcurlをインストールしてください。 現在読み込まれているcurlがSFTPプロトコルをサポートしているかどうかは、Git Bashでリスト14のように入力して確認してください。

curl --version | grep sftp
# 何も表示されなければ、以下を実行してcurlのパスを確認する
which curl

リスト14

 

■エラ-その5:リスト15のようなエラーメッセージが出力される。

Unknown SHA1 object, make sure you are deploying the right branch and it is up-to-date.
Do you want to ignore and upload all files again? [y/N]:

リスト15

原因と対処方法5: .git-ftp.logに、想定しないコミットハッシュが記録されている場合にこのメッセージが表示されます。原因としては、(1)~(3)が考えられます。

  • (1)別のプロジェクトが、同じSFTPサーバー且つ同じパスを利用している。
  • (2)別のブランチを選択状態で、git ftp pushを実行してしまった。
  • (3)開発メンバーの誰かが、git push –force を実施してしまった。

(1)は、「導入手順4. 」の⑤で、別のgit-ftpログファイル名を設定してください。
(2)は、「導入手順4. 」の⑥のように、特定のブランチのみgit ftp pushするようにガードを設けてください。
(3)は、開発メンバーにforce pushしないように周知してください(またはpre-push hookでforceを抑止する仕組みを導入する等)。
(1)~(3)を正しい状態に戻したい場合は、続けて「y」を入力し、全てのファイルをアップロードし直しましょう。 すべてのファイルを上げ直したくない場合は、リスト16のように上げ直したいコミットハッシュをチェックアウトした後、git ftp catchupで.git-ftp.logに反映し、git pushし直しましょう。

git checkout fe6b09f2d35432376f356ea56ed2449290a43d65
git ftp catchup
git checkout master
git ftp push

リスト16

 

■その他のエラーが出る場合:

エラー1~5以外のエラーが表示される場合は、リスト17のように、git-ftpコマンドの「-vv」を利用して、詳細なログを出力するようにすると、原因究明しやすくなります。

git ftp push -vv

リスト17

 

まとめ

git-ftpはコマンドに不慣れな方にとっては、導入が難しいですが、正しく用いることで開発効率を上げることができます。もしエラーが出た際も、エラーメッセージをヒントに対応することで対処することもできます。本稿がその一助となれば幸いです。
次回はWSLとVisual Studio Codeを使用した最新のWebサイト開発環境について書きたいと思います。

コラム執筆

第1ビジネスユニット アカウントサービス第23ユニット

渡邊 賢二

カテゴリ: Webサイト, Webサイト構築
2020年03月18日