git 在“git合并”后保留提交历史

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28407020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 02:54:21  来源:igfitidea点击:

Keep commits history after a 'git merge'

gitgithubmergegit-branch

提问by Kamafeather

When I work on two different features (on two different branches created from the master) it is quite annoying that I will not have the commit history when I proceed with merging.

当我处理两个不同的功能(在从master创建的两个不同分支上)时,当我继续合并时,我不会有提交历史记录是很烦人的。

I'll explain better. When I finish work on Branch-A, I merge it into master. And that's fine, if I git logI see all the commits I made on Branch-A.

我会更好地解释。当我完成Branch-A 的工作时,我将它合并到master 中。这很好,如果我git log看到我在Branch-A上所做的所有提交。

Instead, when I finish work on Branch-Band I try to merge it to master(after that Branch-Ahas been already merged), I have to specify a commit message for the merging (while for the first branch I have not been asked anything). And after the merging to master, if I type git log, I cannot see the commits of the Branch-Bin the history of my masterbranch

相反,当我完成Branch-B 的工作并尝试将其合并到master 时(在Branch-A已经合并之后),我必须为合并指定一条提交消息(而对于第一个分支我还没有问什么)。合并到master 后,如果我输入git log,我在master分支的历史记录中看不到Branch-B的提交

Let's say I have

假设我有

**Branch A**

commit 09b2unfas9d781n2e
    Add more stuff

commit 8uj8masd89jas898a
    Add stuff

**Branch B**

commit 09b2unfas9d781n2e
    Add feature setting

commit 8uj8masd89jas898a
    Add feature

I finish having

我吃完

**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...

while I would like to obtainsomething like:

虽然我想获得类似的东西:

**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...

... that would reflect more exactly the history of the performed commits.

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

I don't get why I can keep the history from just one of the two branches.

我不明白为什么我可以只保留两个分支之一的历史记录。

How can I keep everything clear without those mergecommits that hide/omit the real history of the merged commits?

如果没有那些隐藏/省略合并提交的真实历史的合并提交,我如何保持一切清晰?

回答by Joseph K. Strauss

It looks like the first merge was a fast-forward, and the second one was a three-way merge.

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

Explanation

解释

Git has two versions of merge: fast-forward and three-way. (There are other versions, but that is not what happened here.) The default behavior is to do a fast-forward merge when possible, and otherwise do a three-way merge.

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

A fast-forward merge (you can force this behavior with the option --ff-only, which will cause the merge to fail when fast-forward is impossible) can take place when the commit that is being merged has the current position of the branch in its history. For example:

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

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

Excecuting git merge(with default settings) will result in

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

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

You will also not get a chance to edit the merge commit because there is none. However, once this happens, your other branch will diverge from master (not just be ahead):

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

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

Therefore, Git cannot just move the pointer of master from Gto E2because that will get rid of the changes that were made in Fand G. Instead a three-way merge happens, which create a commit that has two parents, and also has a commit message. Now, master can be moved to this commit. (Notice that in this situation, master and branch-b do NOT point to the same commit.

因此,Git 不能只是将 master 的指针从Gto移动,E2因为这将摆脱在F和中所做的更改G。取而代之的是三路合并,这会创建一个具有两个父级的提交,并且还有一个提交消息。现在,master 可以移动到这个提交。(请注意,在这种情况下,master 和 branch-b 不会指向同一个提交。

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

If you want to have a linear history then you need to use rebase, but be forewarned that if anybody else has seen your branch commits this may lead to issues that are beyond the scope of this answer. Using rebase will involve two steps, rebasing and then fast-forward merge. So, instead of merging you first execute the following while on branch-b, git rebase master. This creates new commits that are copies of the old commits, i.e., the same change-set, author information and message, but new committer information and parent history. (I call the commits E1' and E2' in the illustration to indicate that they are just copies.) The old commits will exist until they are garbage collected, but will not be reachable unless you look at the reflog.)

如果您想拥有线性历史,那么您需要使用 rebase,但请注意,如果其他人已经看到您的分支提交,这可能会导致超出本答案范围的问题。使用变基将涉及两个步骤,变基和快进合并。因此,与其合并,不如先在branch-b上执行以下操作,git rebase master. 这会创建作为旧提交副本的新提交,即相同的更改集、作者信息和消息,但新的提交者信息和父历史记录。(我在插图中将提交称为 E1' 和 E2' 以表示它们只是副本。)旧提交将一直存在,直到它们被垃圾收集,但除非您查看 reflog,否则将无法访问。)

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

Executing git checkout master; git merge --ff-only branch-bwill now fast-forward your changes into master, thereby giving you a linear history.

执行git checkout master; git merge --ff-only branch-b现在会将您的更改快进到 master 中,从而为您提供线性历史记录。

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

回答by Yan Foto

Use rebaseinstead of merge. From the tutorial:

使用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.

如果你检查一个重新定位的分支的日志,它看起来像一个线性历史:所有的工作似乎都是连续发生的,即使它最初是并行发生的。

I imagine that the changes from your Branch-Bcannot be merged using fast-forwardmerging into the master. In such cases a three-way-mergeis done:

我想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.

Git 不是仅仅向前移动分支指针,而是创建一个由这种三向合并产生的新快照,并自动创建一个指向它的新提交。这被称为合并提交,它的特殊之处在于它有多个父级。

I would always rebase my commits before commiting them into the masterto keep the linear history.

在将它们提交到master以保持线性历史之前,我总是会重新设置我的提交。