サーチ…
構文
-
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
-
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
-
git rebase --continue | --skip | --abort | --edit-todo
パラメーター
パラメータ | 詳細 |
---|---|
- 持続する | マージの競合を解決した後、リベースプロセスを再開します。 |
- アボート | リベース操作を中止し、HEADを元のブランチにリセットします。リベース操作が開始されたときにブランチが提供された場合、HEADはブランチにリセットされます。それ以外の場合、HEADは、リベース操作が開始されたときの位置にリセットされます。 |
--keep-empty | その結果、親から何も変わらないコミットを保つ。 |
- スキップ | 現在のパッチをスキップしてリベースプロセスを再開します。 |
-m、--merge | マージ戦略を使用してリベースする。再帰(デフォルト)マージ戦略を使用すると、リベースは上流側の名前の変更を認識することができます。リベースマージは、上流のブランチの上にある作業ブランチからの各コミットを再生することによって機能することに注意してください。このため、マージの競合が発生した場合、私たちの側は、上流から始まって遠くまでリベースされたシリーズであり、それらのブランチは作業ブランチです。換言すれば、辺が入れ替わっている。 |
--stat | 最後のrebaseからアップストリームに変更されたもののdiffstatを表示します。 diffstatは、構成オプションrebase.statによっても制御されます。 |
-x、--exec command | 対話型のリベースを実行し、各コミットと実行command 間で停止する |
備考
リベースはリポジトリの履歴を効果的に書き換えます。
リモートリポジトリに存在するリベースコミットは、他の開発者がその開発のためのベースノードとして使用しているリポジトリノードを書き換えることができます。あなたが何をしているのか本当に分かっていない限り、変更をプッシュする前にリベースするのがベストプラクティスです。
ローカルブランチリベース
リベースは、一連のコミットを別のコミットの上に再適用します。
ブランチをrebase
するには、ブランチをチェックアウトし、別のブランチの上にrebase
します。
git checkout topic
git rebase master # rebase current branch onto master branch
これにより、
A---B---C topic
/
D---E---F---G master
に変える:
A'--B'--C' topic
/
D---E---F---G master
これらの操作を1つのコマンドにまとめると、ブランチをチェックアウトして直ちにリベースすることができます。
git rebase master topic # rebase topic branch onto master branch
重要:リベース後、適用されたコミットは異なるハッシュを持ちます。すでにリモートホストにプッシュしたコミットを再配置しないでください。結果はできないかもしれgit push
ためにあなたの唯一のオプション残して、リモートホストにローカルのリベース後のブランチをgit push --force
。
Rebase:私たちと彼らの、ローカルとリモート
リベースは「私たち」と「彼ら」の意味を変えます:
git checkout topic
git rebase master # rebase topic branch on top of master branch
HEADの指しているものが "私たち"
リベースが最初に行うことは、 HEAD
をmaster
リセットすることです。チェリーピッキングが古いブランチtopic
から新しいブランチtopic
にコミットする前に(前のtopic
ブランチのコミットはすべて書き換えられ、別のハッシュによって識別されます)。
マージツールで使用される用語( ローカルリファレンスまたはリモートリファレンスと混同しないでください)に関しては、
=> local is master ("ours"),
=> remote is topic ("theirs")
つまり、マージ/差分ツールは、 local
( master
:リベースしているブランチ)と作業ブランチをremote
として表示します( topic
:リベースされているブランチ)
+-----------------------------------------+
| LOCAL:master | BASE | REMOTE:topic |
+-----------------------------------------+
| MERGED |
+-----------------------------------------+
イラストレーション
マージ時:
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- other branch to merge
私たちは現在の支店のtopic
変更しないので、私たちはまだ私たちが取り組んでいるものです(そして私たちは別の支店から合併します)
c--c--x--x--x---------o(*) MERGE, still on branch topic
\ ^ /
\ ours /
\ /
--y--y--y--/
^
theirs
リベースの場合:
しかし、リベースでは、リベースが最初に行うことは、上流のブランチをチェックアウトして、その上にある現在のコミットを再生するためです。
c--c--x--x--x(*) <- current branch topic ('*'=HEAD)
\
\
\--y--y--y <- upstream branch
git rebase upstream
のgit rebase upstream
は、まずHEAD
を上流のブランチに設定します。したがって、前回の現在の作業ブランチと比較して、 '私たち'と '自分のもの'の切り替えが行われます。
c--c--x--x--x <- former "current" branch, new "theirs"
\
\
\--y--y--y(*) <- set HEAD to this commit, to replay x's on it
^ this will be the new "ours"
|
upstream
rebaseは新しい '私たちの' topic
ブランチで '彼らの'コミットを再生します:
c--c..x..x..x <- old "theirs" commits, now "ghosts", available through "reflogs"
\
\
\--y--y--y--x'--x'--x'(*) <- topic once all x's are replayed,
^ point branch topic to this commit
|
upstream branch
インタラクティブリベース
この例は、対話モードでgit rebase
どのように利用できるかを記述することを目的としています。 git rebase
が何であるか、それが何をするのかを基本的に理解していることが期待されます。
対話型のリベースは、次のコマンドを使用して開始されます。
git rebase -i
-i
オプションは対話モードを指します 。対話型のリベースを使用すると、ユーザーはコミットメッセージを変更したり、並べ替え、分割、および/またはスカッシュ(1つに結合)コミットを変更することができます。
最後の3つのコミットを再配置したいとします。これを実行するには、以下を実行します。
git rebase -i HEAD~3
上記の命令を実行した後、テキストエディタでファイルを開き、コミットのリベース方法を選択することができます。この例では、コミットの順序を変更し、ファイルを保存してエディタを閉じます。これにより、適用した順序でリベースが開始されます。 git log
をチェックすると、指定した新しい順序でコミットが表示されます。
再コミットメッセージ
さて、コミットメッセージの1つがあいまいであり、それをより説明的にしたいと決めました。同じコマンドを使って最後の3つのコミットを調べてみましょう。
git rebase -i HEAD~3
コミットの順序を並べ替える代わりに、コミットはreword
れます。今回は、デフォルトのpick
を変更して、コミット時にメッセージを変更したい場所にreword
します。
エディタを閉じると、リベースが開始され、リワードする特定のコミットメッセージで停止します。これにより、コミットメッセージをあなたが望むものに変更することができます。メッセージを変更したら、エディタを閉じて続行します。
コミットの内容の変更
コミットメッセージの変更に加えて、コミットによって行われた変更を適応させることもできます。これを行うには、1つのコミットに対してedit
ためにpick
を変更しedit
。 Gitは、そのコミットに到達すると停止し、ステージング領域でのコミットの元の変更を提供します。これらの変更は、ステージングを解除したり、新しい変更を加えたりすることで、適応できます。
ステージング領域にコミットに必要なすべての変更が含まれるとすぐに、変更をコミットします。古いコミットメッセージが表示され、新しいコミットを反映させることができます。
単一のコミットを複数に分割する
コミットしたとしますが、後でこのコミットを2つ以上のコミットに分割することを決定しました。以前と同じコマンドを使用して、代わりにedit
をpick
に置き換え、Enterを押します。
さて、gitはあなたが編集用にマークしたコミットで停止し、すべてのコンテンツをステージングエリアに配置します。その時点からgit reset HEAD^
を実行して、コミットを作業ディレクトリに置くことができます。次に、ファイルを別の順序で追加してコミットすることができます。最終的に、1回のコミットをn回のコミットに分割します。
複数のコミットを1つにまとめる
いくつかの仕事をして、1回のコミットではないと思われる複数のコミットがあるとします。そのためにはgit rebase -i HEAD~3
を実行し、 3
を適切な量のコミットに置き換えてください。
今回はpick
をsquash
に置き換えてください。 rebase中に、あなたが押しつぶされるように指示したコミットは、前のコミットの上で押しつぶされます。代わりにそれらを単一のコミットに変えます。
インタラクティブなRebaseを中止する
対話型のリベースを開始しました。コミットを選択するエディタで、何かが間違っていると判断した場合(たとえば、コミットがない、または間違ったリベース先を選択したなど)、リベースを中断したいとします。
これを行うには、すべてのコミットとアクション(つまり、 #
記号で始まらない行)をすべて削除すると、リベースが中止されます!
エディタのヘルプテキストは実際にこのヒントを提供します:
# Rebase 36d15de..612f2f7 onto 36d15de (3 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Note that empty commits are commented out
リベース後のプッシュ
ときには、リベースを使ってリライトの履歴を書き直す必要があるかもしれませんが、 git push
は履歴を書き換えたのでそうすることについて不平を言います。
これはgit push --force
で解決できますが、 git push --force-with-lease
考慮すると、ローカルのリモート追跡ブランチがリモートのブランチと異なる場合(例えば、誰か)、プッシュを失敗させたいことを示しますそれ以外は最後のフェッチ後にリモートにプッシュされます。これにより、他の誰かの最近のプッシュを誤って上書きすることを防ぎます。
注意 : git push --force
-とさえ--force-with-lease
そのことについては-それはブランチの歴史を書き換えているため、危険なコマンドであることができます。他の人が強制的にプッシュする前にブランチを引っ張った場合、ローカル履歴とリモート履歴が異なるため、 git pull
またはgit fetch
にエラーが発生します。これにより、人に予期しないエラーが発生する可能性があります。 reflogを十分に見れば、他のユーザーの作業を回復することができますが、時間が浪費される可能性があります。他のコントリビュータとブランチに強制的にプッシュする必要がある場合は、エラーを処理する必要がないようにコーディネートしてください。
最初のコミットまで下げる
Git 1.7.12以降、ルートコミットにリベースできます。ルートコミットはリポジトリで初めて作成されたコミットであり、通常は編集できません。次のコマンドを使用します。
git rebase -i --root
コードレビューの前にリベース
概要
この目標は、散らばったすべてのコミットをより意味のあるコミットに再編成して、簡単なコードレビューを行うことです。一度に多くのファイルに変更のレイヤーが多すぎる場合は、コードレビューを行うのが難しくなります。時系列的に作成されたコミットをトピックコミットに再編成することができれば、コードレビュープロセスはより簡単になります(そして、おそらくコードレビュープロセスのバグは少なくなります)。
この過度に単純化された例だけでは、gitを使用してコードレビューを改善する唯一の戦略ではありません。これは私がやる方法であり、コードレビューとgitの履歴をより簡単に/より良くする方法を他の人に奨励するものです。
これは一般的にリベースの力を教育的にも示しています。
この例では、対話型のリベースについて知っていることを前提としています
仮定:
- あなたはマスターのフィーチャーブランチに取り組んでいます
- あなたの機能は3つの主要な層を持っています:フロントエンド、バックエンド、DB
- フィーチャーブランチで作業している間にたくさんのコミットを行っています。各コミットは一度に複数のレイヤーに触れる
- あなたは(最後に)ブランチに3つのコミットしか望みません
- 1つはすべてのフロントエンドの変更を含む
- 1つはすべてのバックエンド変更を含む
- 1つはすべてのDB変更を含む
戦略:
- 私たちは時系列コミットを「局所的」コミットに変更しようとしています。
- まず、すべてのコミットを複数の小さなコミットに分割します。各コミットは、一度に1つのトピックのみを含んでいます(この例では、トピックはフロントエンド、バックエンド、DB変更です)
- 次に、私たちの局所的なコミットを並べ替えて、それらを一回の局所的なコミットにスカッシュします
例:
$ git log --oneline master..
975430b db adding works: db.sql logic.rb
3702650 trying to allow adding todo items: page.html logic.rb
43b075a first draft: page.html and db.sql
$ git rebase -i master
これはテキストエディタで表示されます:
pick 43b075a first draft: page.html and db.sql
pick 3702650 trying to allow adding todo items: page.html logic.rb
pick 975430b db adding works: db.sql logic.rb
これに変更してください:
e 43b075a first draft: page.html and db.sql
e 3702650 trying to allow adding todo items: page.html logic.rb
e 975430b db adding works: db.sql logic.rb
次にgitは一度に1つのコミットを適用します。各コミット後、プロンプトが表示され、次のことができます。
Stopped at 43b075a92a952faf999e76c4e4d7fa0f44576579... first draft: page.html and db.sql
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
$ git status
rebase in progress; onto 4975ae9
You are currently editing a commit while rebasing branch 'feature' on '4975ae9'.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
nothing to commit, working directory clean
$ git reset HEAD^ #This 'uncommits' all the changes in this commit.
$ git status -s
M db.sql
M page.html
$ git add db.sql #now we will create the smaller topical commits
$ git commit -m "first draft: db.sql"
$ git add page.html
$ git commit -m "first draft: page.html"
$ git rebase --continue
その後、コミットごとにこれらの手順を繰り返します。結局、あなたはこれを持っています:
$ git log --oneline
0309336 db adding works: logic.rb
06f81c9 db adding works: db.sql
3264de2 adding todo items: page.html
675a02b adding todo items: logic.rb
272c674 first draft: page.html
08c275d first draft: db.sql
今度はもう一度rebaseを実行して、並べ替えとスカッシュを実行します。
$ git rebase -i master
これはテキストエディタで表示されます:
pick 08c275d first draft: db.sql
pick 272c674 first draft: page.html
pick 675a02b adding todo items: logic.rb
pick 3264de2 adding todo items: page.html
pick 06f81c9 db adding works: db.sql
pick 0309336 db adding works: logic.rb
これに変更してください:
pick 08c275d first draft: db.sql
s 06f81c9 db adding works: db.sql
pick 675a02b adding todo items: logic.rb
s 0309336 db adding works: logic.rb
pick 272c674 first draft: page.html
s 3264de2 adding todo items: page.html
注意:git rebase に、時間順にコミットされた小さなコミットを適用/ 縮退するように指示してください 。さもなければ、虚偽の不要なマージ競合が発生する可能性があります。
そのインタラクティブ・リベースがすべて言われ、実行されると、あなたはこれを得ます:
$ git log --oneline master..
74bdd5f adding todos: GUI layer
e8d8f7e adding todos: business logic layer
121c578 adding todos: DB layer
要約
あなたは時系列コミットを局所的コミットにリベースしました。現実の生活では、これを毎回行う必要はないかもしれませんが、あなたがこれをやりたい、またはする必要があるときに、今できるのです。さらに、うまくいけば、git rebaseについてもっと学んだことでしょう。
マージの代わりに自動的にrebaseを実行するようにgit-pullをセットアップする
チームがリベースベースのワークフローに従っている場合、 git pull
際に、新しく作成された各ブランチがマージ操作ではなくリベース操作を実行するようにgitをセットアップすることが有利かもしれません。
すべての新しいブランチを自動的に.gitconfig
するように設定するには、 .gitconfig
または.git/config
次の行を追加します。
[branch]
autosetuprebase = always
コマンドライン: git config [--global] branch.autosetuprebase always
あるいは、-- --rebase
オプションが渡されたかのように常に動作するようにgit pull
コマンドを設定することもできます:
[pull]
rebase = true
コマンドライン: git config [--global] pull.rebase true
リベース中のすべてのコミットをテストする
プルリクエストを行う前に、コンパイルが成功し、ブランチ内の各コミットに対してテストが合格していることを確認すると便利です。 -x
パラメータを使って自動的に行うことができます。
例えば:
git rebase -i -x make
対話的なrebaseを実行し、 make
を実行make
たびに停止します。 make
が失敗した場合、gitは停止して、問題を修正し、次のものを選ぶ前にコミットを修正する機会を与えます。
オートスタートの設定
Autostashは、ローカル変更にリベースを使用する場合に非常に便利な設定オプションです。多くの場合、上流のブランチからコミットする必要があるかもしれませんが、まだコミットする準備ができていません。
しかし、Gitでは、作業ディレクトリがクリーンでなければ、リベースを開始できません。レスキューへのオートスタート:
git config --global rebase.autostash # one time configuration
git rebase @{u} # example rebase on upstream branch
再起動が完了すると、自動起動が適用されます。リベースが正常に終了したかどうか、または異常終了したかどうかは関係ありません。どちらの方法でも、オートスターシュが適用されます。リベースが成功し、ベースコミットが変更された場合、自動ストッシュと新しいコミットの間に競合が存在する可能性があります。この場合、コミットする前に競合を解決する必要があります。これは、手動で隠してから適用する場合と変わりありませんので、自動的に行うことには欠点はありません。