web-dev-qa-db-ja.com

git:ブランチをマージしますが、コミット履歴は保持します

私のgitワークフローには、1つのメインリポジトリと1つのブランチ、マスターがあります。全員がリモートマスターからプルし、全員がリモートマスターにプッシュします。フィーチャーを準備している間、自分のブランチで働きたいです。これまでのところ、私の歴史は次のようなものです。

git pull --rebase
git checkout -b new_feature
<make some commits>
git checkout master
git pull --rebase

今、私はブランチをマージしたいと思います、そしてこれが私が必要とするものです:

  1. ローカルマスターブランチにマージコミットがありません。
  2. New_featureブランチで行われたすべてのコミットは、マスターで行ったかのようにマスターにマージされました。
  3. マージされたすべてのコミットは、ローカルのリモートヘッドポインタの上のどこかにマージされます。

私の最大の関心事は、変更を安全にプッシュできるようにするために必要な場合の項目3です。マージされたコミットが先頭の前のコミットと絡み合っている場合、プッシュの問題が発生します。関連する問題を参照してください: git:単一のコミットのプッシュ、リベースによる並べ替え、コミットの重複

私は以下を読みました:

そして、私はする必要があると思います:

git checkout master
git pull --rebase
git checkout new_feature
git rebase master
git checkout master
git rebase new_feature
git Push

私の理解はそれです

git checkout new_feature
git rebase master

new_featureは、新しい現在のヘッドから分岐したように見えます。本当?そしてそれ

git checkout master
git rebase new_feature

マスターの上にnew_featureを配置します。あれは正しいですか?もしそうなら、これは私の混乱の主なポイントです。 「gitrebasemaster」がマスターコミットをnew_featureの下部に配置する場合、「git rebase new_feature」がnew_featureコミットをマスターの上部に配置するのはなぜですか。つまり、逆のことをしないのはなぜですか。

14
Samuel

回答

これが、必要なことを実行するために使用できるワークフローです。

git checkout master
git pull --rebase                             (1)
git checkout new_feature                      
<do a bunch of commits>
git rebase master                             (2)
git checkout master
git merge new_feature                         (3)
git branch -D new_feature                     (4)

説明

(1)git pull --rebaseは最初にOrigin/masterをフェッチし、次にローカルのmasterをその上で再生します。サンプルログでは、ローカルコミットが「ローカルリモートHEADポインタ」の上にあることに注意してください。

> git log --oneline --all -10 --decorate

d34d34c (HEAD, master) Local commit message.
d3434r2 Local commit message.
d234d4c Local commit message.
er3ede3 (Origin/master, Origin/HEAD) Remote commit message.
sfe3fd3 Remote commit message.

これで、checkoutを実行して、しばらくの間new_featureブランチで作業できます。終わったら...

(2)git rebase mastermasterの上にnew_featureを再生します。繰り返しますが、ローカルコミットは「ローカルリモートHEADポインタ」」の上に残ります。

> git log --oneline --all -10 --decorate

fc5773d (new_feature) Local new_feature commit.
9282838 Local new_feature commit.
d34d34c (HEAD, master) Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (Origin/master, Origin/HEAD) Remote commit.
sfe3fd3 Remote commit.

rebaseコマンドはnew_featureをマスターの前に置くだけで、それらを整列させるには実行する必要があります...

(3)git merge new_feature、これは早送りマージを実行します。これで、HEADnew_feature、およびmasterはすべて同じコミットを指します。

> git log --oneline --all -10 --decorate

fc5773d (HEAD, new_feature, master) Local new_feature commit.
9282838 Local new_feature commit.
d34d34c Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (Origin/master, Origin/HEAD) Remote commit.
sfe3fd3 Remote commit.

(4)その後、new_featureブランチを安全に削除できます。プッシュする前の最終ログは次のようになります。

> git log --oneline --all -10 --decorate

fc5773d (HEAD, master) Local new_feature commit 2
9282838 Local new_feature commit.
d34d34c Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (Origin/master, Origin/HEAD) Remote commit.
sfe3fd3 Remote commit.
25
Shaun Luttin

New_featureブランチでgit rebase new_featureを実行した後、masterブランチでgit rebase masterを実行する必要はありません。 new_featureブランチでgit rebase masterを実行した後、new_featureをマスターにマージできます。これは早送りマージであり、マージコミットは導入されません。

git rebase new-featureがマスター上ですべての新機能コミットを再生しない理由は、gitがマスターがすでに新機能のベースにあることを認識しているためです-git rebase masterでそのステップを実行しました-そしてそれは自分自身に基づいているだけです。したがって、代わりに、新機能に早送りします。

また、リモート/マスターチップの下にあるコミットをプッシュすることを心配する必要はありません-リモートは、試行した場合にプッシュを拒否します(-fオプションを指定しない限り、そうしません)。また、ローカルマスターがリモートマスターを追跡している場合、git statusはローカルがリモートブランチから分岐したかどうかを通知します。

6
Dan Fischer