在'git merge'之后保留提交历史记录

Kam*_*her 22 git merge github git-branch

当我处理两个不同的功能(在从主服务器创建的两个不同的分支上)时,当我继续合并时,我将不会有提交历史,这非常令人讨厌.

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

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

让我说我有

**Branch A**

commit 09b2unfas9d781n2e
    Add more stuff

commit 8uj8masd89jas898a
    Add stuff

**Branch B**

commit 09b2unfas9d781n2e
    Add feature setting

commit 8uj8masd89jas898a
    Add feature
Run Code Online (Sandbox Code Playgroud)

我完成了

**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...
Run Code Online (Sandbox Code Playgroud)

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

**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...
Run Code Online (Sandbox Code Playgroud)

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

我不明白为什么我可以从两个分支中的一个保留历史.

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

Jos*_*uss 31

看起来第一次合并是快进,第二次合并是三次合并.

说明

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

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

A - B - C - D <-master
             \
              E - F - G <- branch-a
Run Code Online (Sandbox Code Playgroud)

超出git merge(使用默认设置)将导致

A - B - C - D - E - F - G <- branch-a <-master
Run Code Online (Sandbox Code Playgroud)

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

A - B - C - D  - E - F - G <-master
                  \
                   E1 - E2 <- branch-b
Run Code Online (Sandbox Code Playgroud)

因此,Git不能只是将master的指针移动G到,E2因为这将消除在F和中所做的更改G.而是发生三向合并,它创建一个具有两个父项的提交,并且还有一个提交消息.现在,master可以转移到此提交.(请注意,在这种情况下,master和branch-b不指向同一个提交.

A - B - C - D  - E - F - G - H <-master
                  \       /
                   E1 - E2 <- branch-b
Run Code Online (Sandbox Code Playgroud)

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

A - B - C - D  - E - F - G <-master
                  \       \
                   E1 - E2 \ 
                            E1' - E2' <- branch-b
Run Code Online (Sandbox Code Playgroud)

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

A - B - C - D  - E - F - G - E1' -E2' <-master <- branch-b
Run Code Online (Sandbox Code Playgroud)

  • Nvm它确实是`git rebase master`. (4认同)
  • 当两者都有更改时,我需要将master合并到branch-b中。我该如何重写`branch-b`,就像它是从提交`G`而不是`E`开始的?但是要保留“ branch-b”的提交历史记录,并提交对“ branch-b”的冲突更改。假设我只是一个了解`branch-b`的人。 (2认同)

Yan*_*oto 5

使用rebase代替merge。从教程

如果您检查了一个经过重新调整的分支的日志,它看起来就像是一个线性历史记录:看起来所有工作都是串行进行的,即使最初是并行进行的也是如此。

我想您Branch-B无法使用快进合并功能合并您的更改master。在这种情况下,将进行三向合并

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

在将提交提交到之前,我总是会重新整理提交内容,master以保持线性历史记录。

  • 如果您在将本地工作分支合并到 master 之前**仅**对本地工作分支进行变基,那么就不会造成混乱 - 因为没有人在使用您的本地分支。即使是你,在它曾经愉快地加入主人之后。 (2认同)
  • @Kamafeather你是对的!现在到了 2022 年,我被迫总是重新设定基准。我关于变基令人困惑的论点完全是错误的! (2认同)
  • ❤️ 很高兴它帮助改进您的工作流程!它每天都会帮助我整理和保留元数据和差异以调试 git 历史记录。– 尽管有时需要更多的工作或者重写历史很棘手。恕我直言,这是值得的;但你的论点没有错,我理解我的 git rebase 工作流程*可能*令人困惑(iirc 作为新手,我无法掌握 rebase)。对于初学者,我建议坚持使用“merge”,并且“永远不要”从我的 WIP 分支中选择提交(那......我备份到“origin”,前缀为“kama/WIP/feature-5”,等待对任何人大喊大叫这触动了他们)。 (2认同)