Git を使った開発で最もよく利用するコマンドの一つ「git push」。基本動作のおさらいと、よく利用するオプションをまとめました。
git push コマンドの概要
git push はリモートレポジトリのブランチ履歴を更新するための Git コマンドです。
ローカル環境にあるブランチ上で作成されたコミット履歴と関連連する参照(e.g ブランチ名、タグ)を任意のリモートレポジトリに送信することで、そのリモート上でのコミット履歴を更新できます。
下記は git push origin master を実行した際のイメージです。origin レポジトリに、ローカルのmaster ブランチを送信します。origin 上の、同名のブランチ(ここでは master ブランチ)が更新されます。
git push コマンドの使い方
それでは、git push コマンドの具体的な使い方を見ていきます。git push は引数の特別な指定方法や、省略記法が存在します。それぞれの仕様を把握しておきましょう。
ブランチを指定して、リモートにある同名ブランチに push する
冒頭でも紹介した、最も典型的な git push の利用例です。リモートレポジトリ名と、push したいローカルブランチを指定すれば、リモート上にあるローカルと同名のブランチが更新されます。
// ローカルブランチ「master」を、リモートレポジトリ「origin」上の同名のブランチに反映する
git push origin master
もし、ローカルの履歴が、リモートの履歴とコンフリクトする場合、エラーになり、push は失敗します。
このような場合「-f 」オプションで強制的に上書きすることもできますが、こちらについては詳しくは後述します。
更新するリモートブランチ名を明示的に指定して push する
前述の通り「git push <remote> <branch>」は、通常は第二パラメータで指定したローカルブランチと「同じ名前のリモートブランチ」を更新します。一方で、ブランチ名の指定する引数に「:(コロン)」を用いれば、push 先となるリモートブランチを明示的に指定する事もできます。
例えば下記は、現在のローカルブランチ「master」をリモートにある「master」に push する事になります。
// ローカルブランチ「master」を、リモートブランチ「master」に push
git push origin master:master
多くの場合、同名のブランチやに push する事がほとんどですので、このような引数を指定することは稀だと思います。
ただし、このコロンには下記のような「ブランチ削除」の使い方もあるので、覚えておくとよいでしょう。
git push でのコロンの使い方?
git push では、「:(コロン)」を使った表現は、リモートブランチの削除コマンドとしても利用できます。
// リモートブランチ「tmp」を削除
git push origin :tmp
コロンの前にブランチ名が指定されていませんが、これは「空」を意味します。「空をリモートに送信する」すなわた、指定したリモートブランチを消去するという意味になります。ブランチの削除に関しては、後述の「--delete」オプションもありますので、どちらを使っても構いません。
ブランチ名の引数を省略して、上流ブランチに push する
ブランチ名を省略することもできます。この場合、デフォルトの振る舞いは「現在チェックアウトしているブランチを、その上流ブランチに push することになります。
// もし現在、ローカルブランチ「master」をチェックアウトしていれば、
// 「master」をリモートブランチ「master」にpush
git push origin
もし上流ブランチが設定されていなければ、エラーとなります。
// 引数を省略して push
$ git push origin
// 上流ブランチが設定されていなければエラー
fatal: The current branch tmp has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin tmp
「上流ブランチ」について、よく解らない場合は、こちらもあわせてご一読下さい。
git push 引数を省略した時の振る舞いについての詳細
さて、上記はあくまで、push 先ブランチ名が指定されなかった場合「デフォルトの」振る舞いでした。これに関して、より詳細な仕様を見てみましょう。
push 先のブランチ名が指定されなかった場合、実際にはこれに関する config 設定値によって振る舞いが決まります。
まず、最初はPush先のブランチを探します。最初、設定値「remote.<repository>.push」の値が参照されますが、設定値はデフォルトでは空となっているはずです。この値にはrefspec(参照仕様)を記述することになっており、例えば、下記のような指定が可能です。
// origin レポジトリの、masterブランチのpush に関するの設定値
[remote "origin"]
push = refs/heads/master:refs/heads/master
この設定によりブランチ引数省略時、すなわち「git push origin」を実行した時、引数の代わりにこの設定がそのまま利用されることになります。意図的に引数を省略して、同じ push を短いコマンドで実行したいときに利用できる設定値です(筆者は使ったことはありません・・)
ただし、多くの場合、上記のpush 設定値が存在しないはずです。その場合、その次に push の方針を決定する「push.default」の設定値を参照します。こちらもデフォルトでは空ですが、下記のような設定が可能です。
push 方針に関する設定値「push.default」の一覧
push.default という設定値は、下記の値のいずれかを設定できます。
設定値 | 振る舞い |
---|---|
nothing | 引数でブランチ指定がなければ、エラーを発生して何もしない。 |
current | 現在チェックアウトしているブランチと同名のブランチを更新する。 |
upstream | 上流ブランチに設定されているブランチに Push する |
simple | 上流レポジトリへのpush であれば「upstream」のように振る舞うが、もしブランチ名が異なる場合はpush を中止する。もし別のリモートレポジトリへの push であれば「current」のように振る舞う。(デフォルト値) |
matching | ローカルのすべてのブランチを、リモートの同名のブランチに push する。 |
push.default が見つかれなければ、最終的に設定値「simple」の方針にフォールバックする事になっています。すなわち、多くの引数なしPUSHは、simple の設定値として動作することになります。
デフォルトのpush 方針となる「simple」は、一見やや変速的な仕様に見えますが、要は「通常は現在のブランチを、その上流ブランチへ」「上流ブランチでも、ブランチ名前がローカルと異なれば、安全のため停止」「上流ブランチでないリモートにpushするケースは、現在のブランチと同じ名前のリモートブランチにpush」という、最も直感的な仕様となっていると思います。
この「simple」は、Git のバージョン2移行デフォルトとなりましたが、それ以前は「matching」がデフォルトでした。ですので、古いネット上の情報では「ブランチ名を省略すると全部のブランチがpush される」といった内容の記事も散見されますが、最新バージョンの Git を使っているのであれば、そのようなことはありません。
より詳しくは、Git ドキュメントをあわせてご覧下さい。
引数をすべて省略して、 上流ブランチへ push する
git push はレポジトリのパラメータも省略することができます。
下記のようにレポジトリが省略された場合、デフォルトでは、現在のブランチの上流ブランチtとして設定されているレポジトリのブランチが push 先になります。正確には「branch.<branch_name>.remote」の値です。
Git 運用に慣れてくれば、多くの場合、このコマンドで push してしまう事がほとんどでしょう。コマンドが短いので、すばやく実行できます。
// リモートとブランチ名を省略してpush
git push
また、もし上流ブランチの設定値がない場合は、デフォルトで「origin」が Push 先のレポジトリになります。
git push を強制し、リモートブランチを上書きする
もし push しようとしているローカルの履歴が、リモートブランチの履歴がコンフリクト(競合)してしまう場合、エラーとなり、git push はストップします。git push には、これを強制的に push し、上書きしてしまうオプション「-f, --force」が存在します。
// git pushを強制するオプション (2つは同義) git push -f origin master git push --force origin master
【補足】git push を強制する時の注意
通常、チームで開発していると、みんなが参照するブランチ(例えばmasterブランチ)があるはずです。
あなたの都合でmasterを勝手に強制上書きすると、他のメンバーの人がfetchしてローカルに落としたmasterの履歴と、リモートにあるmasterの履歴が異なってしまいます。それを、あなたの先輩が気づかずに、古いmasterに徹夜して重要な修正をたくさん追加して、ローカルで入念にテストして、朝方くたくたになって、Pushすると・・・、コンフリクトがででています・・。あなたが勝手に歴史を書き換えたからです。先輩は、存在しない歴史(=消された古いコミット)の上に自分の変更をたくさん積み重ねてしまったため、リベースが大変です。あなたは、次の日、説教部屋に呼び出されてしまいました。。
さて、今回は、先輩とあなたの間だけの話でしたが、チームの規模が大きくなればなるほど、このような事件に巻き込まれれる人や、被害が増えてしまいます。
git push -f は、通常のチームでの共有しているブランチ行う時は、注意が必要です。
もし共有されているブランチの修正の必要が生じたら、できるだけ歴史を書き換えることなく、その修正を「新しいコミット」にして、追加Pushして下さい。そうすれば、チームメンバーが、その修正コミットだけを後からマージし易いはずです。
フックの利用
git push の実行時に特定の動作を関連付けることができます。
git push コマンドの主要なオプション
プッシュを強制する「-f, --force )」
上述の通り、git push は「-f」オプションで、ローカルとリモートので履歴のコンフリクトが発生する場合でも、強制的にリモートを上書きできます。使用するときは、注意が必要です。
// git pushを強制するオプション
$ git push -f origin master
$ git push --force origin master
ローカルが新しいときだけ強制する「--force-with-lease」
git push --force と似ていますが、ローカルがリモートよりも履歴が新しいときだけ強制します。
// 履歴が新しいときだけ git pushを強制するオプション
$ git push --force-with-lease origin master
上流ブランチを設定する「-u, --set-upstream」
下記のpushコマンドに「-u」オプションをつければ、同名の上流ブランチを設定できます。上述の通り、git push が成功すれば、その後はパラメータを省略して push できるようになりますので、設定しておきましょう。
// Push と同時に、上流ブランチに設定する
$ git push -u origin maste
$ git push --set-upstream origin master
指定したブランチを削除する「--delete」
--delete オプションで、指定したリモートブランチを削除することができます。
// origin の cool-feature ブランチを削除
git push origin --delete cool-feature
すべてのブランチを push する「--all」
--all でローカルのすべてのブランチを push します。この場合、ブランチ名は指定することができません。この場合 config の push.default の設定値があれば、それに応じて振る舞いが変わります。
// すべてのローカルブランチをorigin に Push
git push --all origin
リモートに存在しないブランチを削除する「--prune」
ローカルに存在するが、リモートに存在しないブランチを削除します。
// すべてのローカルブランチをorigin に Push
git push --prune origin
すべてのタグを push する「--tag」
すべてのタグをpushします。
// すべてのローカルブランチをorigin に Push
git push --tags origin
git push に関する参考情報
Git Documentサイトです。