关于github:在’git merge’之后保持提交历史记录

Keep commits history after a 'git merge'

当我处理两个不同的特性(在从master创建的两个不同的分支上)时,当我继续合并时,我将没有提交历史记录,这非常令人恼火。

我会解释清楚的。当我完成分支A的工作时,我将它合并到master中。好吧,如果我看到我在A分局所做的一切。

相反,当我完成branch-b的工作并尝试将它合并到master(在branch-a已经合并之后),我必须为合并指定一个提交消息(而对于第一个分支,我没有被要求任何东西)。在合并到master之后,如果我键入git log,在我的master branch的历史中就看不到b分支的承诺了。

假设我有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
**Branch A**

commit 09b2unfas9d781n2e
    Add more stuff

commit 8uj8masd89jas898a
    Add stuff

**Branch B**

commit 09b2unfas9d781n2e
    Add feature setting

commit 8uj8masd89jas898a
    Add feature

我吃完了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
**Master**

commit 6hf6h8hd871udjkdn
Merge: 09b2un 34osd6
    Merge branch 'Branch-B' into master

commit 09b2unfas9d781n2e
    Add more stuff

commit 8uj8masd89jas898a
    Add stuff

commit 34osd62dhc91123j8
    I'm a previous commit from 'master'.
    The last one before branching...

而我想得到的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
**Master**

commit 09b2unfas9d781n2e
    Add feature setting

commit 8uj8masd89jas898a
    Add feature

commit 09b2unfas9d781n2e
    Add more stuff

commit 8uj8masd89jas898a
    Add stuff

commit 34osd62dhc91123j8
    I'm a previous commit from 'master'.
    The last one before branching...

…这将更准确地反映已执行提交的历史。

我不明白为什么我能把历史从两个分支中的一个分支中保留下来。

如果没有隐藏/忽略合并提交的真实历史记录的合并提交,我如何才能保持所有内容的清晰?


看起来第一次合并是快进的,第二次是三方合并。

解释

Git有两个版本的合并:快进和三向。(还有其他版本,但这不是这里所发生的。)默认行为是在可能的情况下执行快进合并,否则执行三向合并。

当要合并的提交在其历史中具有分支的当前位置时,可以进行快进合并(您可以使用选项--ff-only强制此行为,这将导致合并在不可能快进时失败)。例如:

1
2
3
A - B - C - D <-master
             \
              E - F - G <- branch-a

执行git merge(默认设置)将导致

1
A - B - C - D - E - F - G <- branch-a <-master

您也不会有机会编辑合并提交,因为没有合并提交。但是,一旦发生这种情况,您的另一个分支将与主分支分离(不仅仅是在前面):

1
2
3
A - B - C - D  - E - F - G <-master
                  \
                   E1 - E2 <- branch-b

因此,git不能只将master的指针从G移动到E2,因为这样可以消除FG中所做的更改。相反,会发生三方合并,这将创建一个具有两个父级的提交,并且还具有一个提交消息。现在,可以将master移动到此提交。(注意,在这种情况下,master和branch-b并不指向同一个commit。

1
2
3
A - B - C - D  - E - F - G - H <-master
                  \       /
                   E1 - E2 <- branch-b

如果您想要有一个线性历史,那么您需要使用REBASE,但是要预先警告,如果有人看到您的分支提交了,这可能会导致超出此答案范围的问题。使用REBASE将涉及两个步骤,即重新定位,然后快速向前合并。因此,在branch-b上,不要合并,而是先执行以下命令,git rebase master。这将创建新提交,这些提交是旧提交的副本,即相同的更改集、作者信息和消息,但新提交者信息和父历史记录。(我在图中调用提交e1'和e2'以表明它们只是副本。)旧提交将存在,直到垃圾收集它们为止,但除非您查看reflog,否则无法访问它们。)

1
2
3
4
A - B - C - D  - E - F - G <-master
                  \       \
                   E1 - E2 \
                            E1' - E2' <- branch-b

执行git checkout master; git merge --ff-only branch-b现在可以快速地将您的更改向前推进到master,从而给您一个线性历史。

1
A - B - C - D  - E - F - G - E1' -E2' <-master <- branch-b


rebase代替merge。从教程中:

If you examine the log of a rebased branch, it looks like a linear
history: it appears that all the work happened in series, even when it
originally happened in parallel.

我想您的Branch-B的更改不能通过快速向前合并到master来合并。在这种情况下,可以通过三种方式进行合并:

Instead of just moving the branch pointer forward, Git creates a new
snapshot that results from this three-way merge and automatically
creates a new commit that points to it. This is referred to as a merge
commit, and is special in that it has more than one parent.

在把我的承诺提交到master以保持线性历史之前,我总是重新平衡我的承诺。