在Git中,来回合并后,为什么分支不在同一点?

In Git, after merging back and forth, why aren't the branches at the same point?

根据我的理解,我们一直在用 Git 做一个非常标准的分支模型的项目,如下所述:http://nvie.com/posts/a-successful-git-branching-model/

我们从 "master" 开始并从中分支 "develop"。 "develop" 有很多提交,然后我们从 "develop" 分支 "release-1"。有一些提交到 "release-1",然后我们将 "release-1" 合并到 "master",然后再次将 "release-1" 合并到 "develop"。然后我们删除了"release-1".

现在我希望 "master" 和 "develop" 分支在同一点。他们确实有相同的文件,但根据分支图,他们有完全不同的历史,唯一的共同点是存储库中的第一次提交。

所以两个问题:

1) 为什么他们没有相同的历史/为什么他们不在同一点?

2) 我们该如何解决?我们应该强制合并 "develop" 到 "master" 还是 "master" 到 "develop"?

git 对不同的操作创建不同的提交是正常行为:

一个提交跟踪一堆信息:它的parents、它的作者、它的创建日期、它的提交者和最后一次提交日期。

如果这些信息中的任何一个不同,git 将创建两个不同的提交。

例如:将release-1合并为master,然后将release-1合并为develop

  • 如果 masterdevelop 的起点不是完全相同的提交,则两个合并提交将不会具有相同的 parents ;

  • 除非你运行两个命令都以光速发出,否则它们不会有相同的时间戳。


提交中的文件内容称为 tree

git 还保留了提交内容的哈希值,您可以使用 :

查看它
git rev-parse master^{tree}
git rev-parse develop^{tree}

您可以通过查看它们的树哈希来确认这两个提交具有完全相同的内容。


如果你想让 developmaster 指向同一个提交,你可以硬设置 developmaster :

git branch -f develop master

在您的合并过程中,您可以通过以下方式达到相同的状态:

  1. 合并 release-1master

  2. 告诉git“快进”developmaster

    git checkout develop
    git merge --ff-only master
    

    git merge --ff-only :

    • git 将首先检查 master's 历史是否包含 develop 的完整历史,
    • 如果是,它会将 develop 移动到 master(而不是创建新的提交),
    • 否则,它将打印警告并保持 develop 不变。

正如 LeGec 所说,提交是根据各种信息生成的,包括应该使其成为 unique/identifieable 的 author, committer, parent commit, and more

从你的描述来看,你的情况是这样的:

Master  | M1 -------------------------> M2 (merge commit)
--------    \                          /
Release |    \                R1 -> R2
--------      \              /         \ 
Develop |      D1 -> D2 -> D3 --------> D4 (merge commit)            

正如您在案例中所描述的,M2 和 D4 中的文件将相同,但它们的父提交和创建时间将不同。

这不太可能给您带来问题,因为您的工作将在 develop 上继续进行,下次您可以愉快地遵循发布工作流程。由于您没有独立地提交 master,因此您不应该 运行 陷入合并冲突。

如果您希望 "fix it",即给他们一个共同的提交,您可以将 master 合并到 develop,但除了额外的合并提交。

Master  | M1 -------------------------> M2 (merge commit)
--------    \                          /   \ 
Release |    \                R1 -> R2      \
--------      \              /         \     \
Develop |      D1 -> D2 -> D3 --------> D4 -> D5 (merge commit)

注意,这是假设您没有执行快进合并。