git push コマンドはローカルリポジトリのコンテンツをリモートリポジトリにアップロードするときに使用します。プッシュとは、コミットをローカルリポジトリからリモートリポジトリに送る操作です。git push は git fetch と対をなすコマンドで、フェッチはコミットをローカルブランチにインポートするのに対し、プッシュはコミットをリモートブランチにエクスポートします。リモートブランチは git remote コマンドで設定できます。プッシュは変更を上書きする可能性があるため、使用の際は注意が必要です。この問題は下で説明します。

git push の使用方法

git push <remote> <branch>

付随するすべてのコミットおよび内部オブジェクトと共に指定したブランチを <remote> にプッシュするコマンドです。このコマンドを実行すると、プッシュ先のリポジトリにローカルブランチが作成されます。コミットが誤って上書きされるのを防止するために、Git ではプッシュ先リポジトリにおける統合処理が早送りマージ以外である場合にはプッシュが拒否されます。

git push <remote> --force

上のコマンドと同様ですが、早送りマージ以外の場合にも強制的にプッシュが実行されます。プッシュ操作によって何が起こるかを完全に理解している場合以外は --force フラグを使用しないでください。

git push <remote> --all

すべてのローカルブランチを指定したリモートリポジトリにプッシュするコマンドです。

git push <remote> --tags

ブランチをプッシュしたり、--all オプションを指定したりしても、それだけでタグが自動的にプッシュされることはありません。--tags フラグを指定することで、すべてのローカルタグをリモートリポジトリに送ることができます。

git push に関する話

git push は、ローカルの変更を中央リポジトリに公開、アップロードするとき、最もよく使用されるコマンドです。ローカルリポジトリに変更を加えたあと、push コマンドを実行すると、変更をリモートのチームメンバーと共有できます。

git push を使用して変更を公開

上図は、ローカルの master が中央リポジトリの master を追い越して進行し、その状態で git push origin master コマンドを実行して変更を公開すると何が起こるかを示しています。git push がリモートリポジトリ内で git merge master コマンドを実行する場合と本質的に同等であることに留意してください。

git push と同期

git push は Git の "同期" プロセス全体で使用する多くのコンポーネントの 1 つです。これらの同期コマンドを使用するリモートブランチは、git remote コマンドで設定します。git push は "アップロード" コマンド、git fetch コマンドと git pull コマンドは "ダウンロード" コマンドと見なすことができます。ダウンロードやアップロードでチェンジセットを移動すると、移動先で git merge を実行して変更を統合できます。

ベアリポジトリにプッシュ

よくある最新の Git の使用事例に、リモートでホスティングしている --bare リポジトリを中央の origin リポジトリとして機能させる方法があります。この origin リポジトリは、Bitbucket などの信頼されたサードパーティを使用して、オフサイトでホスティングされることがよくあります。プッシュはリモートリポジトリのブランチ構造を変更する操作であるため、--bare フラグを指定して作成したリポジトリにプッシュする方法が、最も安全性が高く一般的です。ベアリポジトリは作業ディレクトリを持たないため、プッシュしても、作業中のディレクトリのコンテンツは一切変更されません。ベアリポジトリの作成については、git init のチュートリアルを参照してください。

強制プッシュ

Git では、プッシュの結果として早送りマージ以外の処理が必要となる場合、中央リポジトリの上書きを防止するためにプッシュリクエストは拒否されます。したがって、リモートリポジトリとローカルリポジトリが分岐状態にある場合は、最初にリモートブランチをプルしてローカルブランチにマージし、その後再度プッシュを試みる必要があります。これは、SVN でチェンジセットをコミットする前のローカルリポジトリをリモートリポジトリに同期する際に svn update コマンドを使用する場合と似ています。

--force フラグを指定すると、この制限が解除され、リモートリポジトリのブランチをローカルリポジトリのブランチに一致させるため、最後にプルした時点以降にリモートリポジトリで変更が発生していた場合はそれらがすべて削除されます。強制プッシュが必要となる唯一のケースは、公開したばかりのコミットに不具合が見つかり、git commit --amend コマンドまたはインタラクティブリベースを使用して、それを修正した場合です。ただしこの場合でも、--force オプションを適用する前に、不具合のあるブランチをプルした開発者は一人もいないと確信できる場合に限り実行します。

デフォルトの git push

次の例は、ローカルな作業成果を中央リポジトリに公開する一般的な方法を示しています。最初に、ローカルの master を間違いなく最新状態にするために、中央リポジトリの master をフェッチし、ローカルな変更をその上にリベースします。ここでコミットを共有する前にインタラクティブリベースを活用してコミットを整理するとよいでしょう。次に git push コマンドを使用してローカルの master 上のコミットをすべて、中央リポジトリに送ります。

git checkout master
git fetch origin master
git rebase -i origin/master
# Squash commits, fix up commit messages etc.
git push origin master

ローカルの master が最新状態になっていることはすでに確認しているため、マージは必然的に早送りマージとなり、git push を実行しても、先に述べた早送りマージ以外の統合処理に起因する問題は発生しません。

修正後の強制 push

git commit コマンドでは、前回のコミットを更新する --amend オプションを指定できます。コミットメッセージや新しい変更の更新時に、コミットを修正することはよくあります。コミットを修正すると、修正後のコミットとリモートコミットが Git によってコンテンツの食い違いとして認識されるため、git push が失敗します。修正後のコミットをプッシュするときは --force オプションを使用する必要があります。

# make changes to a repo and git add
git commit --amend
# update the existing commit message
git push --force origin master

上の例では、コミット履歴を持つ既存のリポジトリでの実行を前提としています。前回のコミットを更新するために、git commit --amend を使用したあと、--force オプションを使用して、修正後のコミットを強制プッシュしています。

リモートブランチまたはタグを削除

会計上または組織の事情により、ブランチのクリーンアップが必要になることがあります。ブランチを完全に削除するには、ローカルとリモートでの削除が必要です。

git branch -D branch_name
git push origin :branch_name

上のコマンドでは "branch_name" というリモートブランチが削除され、前にコロン (:) の付いたブランチ名を git push に渡すことで、このリモートブランチが削除されます。