[解決済み] git rebase と git merge --ff-only の違いは何ですか?
質問
読む限りでは、どちらもリニアな履歴を得るのに役立つようです。
私が実験したところでは、rebase は常に動作します。しかし、merge --ff-onlyは早送りできるシナリオでのみ動作します。
また、git merge はマージコミットを作成しますが、--ff-only を使用すると、本質的に git rebasing と等しい線形履歴を与えることに気づきました。つまり、--ff-only は git merge の目的を殺しているのですね?
では、実際に両者の違いは何なのでしょうか?
どのように解決するのか?
以下のことに注意してください。
git rebase
は、異なる
ジョブ
よりも
git merge
(ありでもなしでも
--ff-only
). 何
rebase
が行うのは、既存のコミットを取り込んで
をコピーすることです。
を行うことです。 たとえば、あなたが
branch1
にいて、二つのコミットを行ったとします。
A
と
B
:
...-o--o--A--B <-- HEAD=branch1
\
o--C <-- branch2
で、この二つのコミットは、むしろ
branch2
に置くことにしました。 できます。
-
で行った変更の一覧を取得する。
A
(差分A
の親に対して) -
で行った変更の一覧を取得します。
B
(差分B
に対してA
) -
に切り替えます。
branch2
-
で行ったのと同じ変更を
A
で行ったのと同じ変更を行い、コミットし、コミットメッセージをA
このコミットをA'
-
で行ったのと同じ変更を
B
で行ったのと同じ変更を行い、コミットし、コミットメッセージをB
と呼びましょう。B'
.
このdiffとcopyとcommitを行うgitコマンドがあります。
git cherry-pick
. というわけです。
git checkout branch2 # switch HEAD to branch2 (commit C)
git cherry-pick branch1^ # this copies A to A'
git cherry-pick branch1 # and this copies B to B'
これで、こうなりました。
...-o--o--A--B <-- branch1
\
o--C--A'-B' <-- HEAD=branch2
これで、再び
branch1
に戻り、元の
A
と
B
を使用すると
git reset
(私が使うのは
--hard
を使うことにします。その方が作業ツリーもすっきりするので便利です)。
git checkout branch1
git reset --hard HEAD~2
これは、元の
A
と
B
,
1
ということで、これで
...-o--o <-- HEAD=branch1
\
o--C--A'-B' <-- branch2
これで、再チェックアウトする必要がある
branch2
を再チェックアウトしてそこで作業を続ける必要があります。
これは
git rebase
これはコミットを移動させます (ただし、実際に移動させることはできません。git ではコミットを変更することはできないので、親 ID を変更するだけでも新しい別のコミットにコピーする必要があります)。
言い換えれば
git cherry-pick
は自動的な差分とやり直しで
1
のコミットです。
git rebase
をやり直す自動化されたプロセスです。
複数の
さらに、最後にラベルを移動してオリジナルを忘れたり隠したりします。
上記は、あるローカルブランチからコミットを移動する様子を示しています。
branch1
から別のローカルブランチ
branch2
というように、gitでは
全く同じ処理
を実行したときに新しいコミットを取得するリモート追跡ブランチがある場合、コミットを移動させるためにまったく同じ処理を行います。
git fetch
を実行したときに新しいコミットを取得するリモート追跡ブランチがある場合 (これには
fetch
の最初のステップである
git pull
). まずブランチ
feature
の上流にある
origin/feature
の上流にある
...-o <-- origin/feature
\
A--B <-- HEAD=feature
しかし、上流で何が起こったかを確認する必要があると判断し、次のように実行します。
git fetch
,
2
そして、上流の誰かがコミットした
C
:
...-o--C <-- origin/feature
\
A--B <-- HEAD=feature
この時点では、単に
feature
's
A
と
B
にかけて
C
を与える。
...-o--C <-- origin/feature
\
A'-B' <-- HEAD=feature
これらは、あなたのオリジナルの
A
と
B
であり、オリジナルはコピー完了後に捨てられる(ただし脚注1参照)。
リベースするものがない、つまり、あなた自身が行った作業がないこともあります。 つまり、グラフの前の
fetch
はこのようになります。
...-o <-- origin/feature
`-- HEAD=feature
もし、あなたが
git fetch
とコミットして
C
が入ってくるのですが、このとき残されるのは
あなたの
feature
ブランチは古いコミットを指し示し、一方
origin/feature
は先に進んでいます。
...-o--C <-- origin/feature
`---- <-- HEAD=feature
これは
git merge --ff-only
の出番です。現在のブランチをマージするように頼むと
feature
と
origin/feature
のように、矢印を前方にスライドさせることが可能であることを git は理解しています。
feature
が直接コミットを指すようになります。
C
. 実際のマージは必要ありません。
自分自身のコミットがあった場合
A
と
B
にマージしてほしいという要望がありました。
C
を指定すると、git は本当の意味でのマージを行い、新しいマージコミット
M
:
...-o--C <-- origin/feature
\ `-_
A--B--M <-- feature
ここで
--ff-only
は停止してエラーを出します。 一方、Rebase は
A
と
B
から
A'
であり
B'
を削除し、元の
A
と
B
.
要するに(もう遅いか:-))、これらは単に異なることをするのです。 結果は同じこともあれば、そうでないこともあります。 もしコピーするのがOKなら
A
と
B
を使用することができます。
git rebase
を使うこともできますが、何か正当な理由がある場合は
ではなく
を使うことができます。
git merge
で、おそらく
--ff-only
で、適宜merge-or-failします。
1
Git は実際にはオリジナルをしばらく(この場合は通常一ヶ月間)保持しますが、それを隠しておきます。 これを見つける最も簡単な方法は、git の "reflogs" で、各ブランチがどこを指していたのか、そしてどこを指していたのかを履歴として残しておくのです。
HEAD
を更新する前に、それぞれのブランチがどこを指していたのか、そして HEAD
.
最終的に reflog の履歴エントリは期限切れになり、その時点でこれらのコミットは ガベージコレクション .
2
あるいは、やはり
git pull
を実行することによって始まる便利なスクリプトです。
git fetch
. 取得が完了すると、コンビニエンス・スクリプトは以下のいずれかを実行します。
git merge
または
git rebase
というように、設定や実行の仕方によって異なります。
関連
-
undefinedGit Git がファイルをコードクラウドにプッシュする際に報告されるエラーを解決します: ! [拒否] master -> master (最初にフェッチ)
-
git reset --hardとgit reset --softの違いについて
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] Git リポジトリでのマージの衝突を解決するには?
-
[解決済み] まだプッシュされていない Git マージを元に戻す
-
[解決済み] git rebase の取り消し
-
[解決済み] git add -A」と「git add .」の違い。
-
[解決済み] Gitブランチをmasterにマージする最も良い(そして最も安全な)方法は何ですか?
-
[解決済み】Gitのワークフローとrebaseとmergeの質問
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
undefinedGit Git がファイルをコードクラウドにプッシュする際に報告されるエラーを解決します: ! [拒否] master -> master (最初にフェッチ)
-
gpg: "xxx" をスキップ: 秘密鍵のための1つの解決策が利用できない
-
git reset --hardとgit reset --softの違いについて
-
[Gitラーニングノート】Gitのコンフリクト:マージする前に変更をコミットするかstashする。
-
gitlabの紹介と使い方
-
gitの利用(ssh鍵の作成とgithubの利用)。
-
[解決済み] JenkinsのGitプラグイン。特定のタグをビルドするには?
-
[解決済み] ローカルのGitブランチをリモートレポにコピーする方法
-
[解決済み] git add --patch' で新しいファイルをインクルードする?
-
[解決済み] Git の 'master' ブランチを 'release' にリネームするには?