我知道有一些情况会导致 Git 提交被重复,例如 git cherry-pick
。如果一个提交被精心挑选并“merge ”到另一个分支中,它会在提交图中出现两次,并带有两个提交哈希值。
Git 是否有可能在 git merge
操作期间重复提交?
我问的原因是以下提交图(在 TortoiseGit 中生成):
提交在此处以“日期顺序”(作者日期)列出。
在我在绿色分支(当时是我的 master
分支)提交 efb916..
之后,我将绿色分支 merge 到红色分支(这是一个本地侧枝)。这在图中显示为常规 merge 。到目前为止一切顺利。
之后,我在 Github for Windows 中点击了 Sync 按钮,将本地 master
同步到远程 origin/master
。这从远程分支中提取了提交 09067c..
,然后 merge 或重新定位本地 master
,因此提交 09067c..
之后是提交efb916..
。然而,Git 并没有真正地 merge efb916..
到09067c..
,而是复制了提交 efb916..
并给出了复制新哈希 48e314..
.
最后,我的master
指向了48e314..
(图中的黑色分支),而我的本地分支指向了68b78a..
(红色分支)。提交 efb916..
和 48e314..
的内容、日期、作者和消息完全相同。
这已经发生了好几次,有时只有一个提交被重复,有时有多个提交。
为什么 git 重复提交 efb916..
?我该如何预防?
编辑: 作为附加说明:我觉得很奇怪,我的 master
最初指向 efb916..
,但在 Github Sync 之后efb916..
不再在 master
的提交历史中。
最佳答案
所以,我将首先将其分解为一个简单的 View 。但这并不完全准确,但更容易掌握。然后我会为您提供进一步阅读的资源。
简单 View
问题是您对提交的真正含义感到困惑。提交哈希不是你的补丁的哈希,它更像是整个系统的哈希。因此,当您 merge 时,它会在功能上应用您正在 merge 的两个(或更多)分支中的所有补丁,产生一个新的完整代码树,并在对象树中创建它,并使用代表当前状态的哈希.
rebase 类似:您在功能上移动树中的所有补丁,结果会有所不同。它们是不同的,因为应用补丁的顺序很重要并会影响散列。实际上,您可以将此作为一个简单的测试来显示差异:
使用单个文件创建一个新的存储库:
# echo "a" >> file
# git init
Initialized empty Git repository in /home/hardaker/tmp/h/test/.git/
# (master #): git add file
# (master #): git commit -m "new file"
[master (root-commit) 9617f27] new file
1 file changed, 1 insertion(+)
create mode 100644 file
现在,让我们对其进行分支:
# (master): git checkout -b new-branch
Switched to a new branch 'new-branch'
在分支中添加一个新文件:
# (new-branch): echo "file2" > file2
# (new-branch): git add file2
P# (new-branch +): git commit -m "new file2" file2
[new-branch 04f3fdf] new file2
1 file changed, 1 insertion(+)
create mode 100644 file2
再次检查 master 并在那里进行更改:
# (new-branch): git checkout master
Switched to branch 'master'
# (master): echo "b" >> file
# (master *): git commit -m "added b" -a
[master 3b3de88] added b
1 file changed, 1 insertion(+)
现在,让我们以树形形式显示日志,看看到目前为止我们有什么:
# (master): git log --oneline --graph --all --decorate
* 3b3de88 (HEAD, master) added b
| * 04f3fdf (new-branch) new file2
|/
* 9617f27 new file
一个漂亮的 TreeView ,有两个分支。注意提交ID new-branch,因为当我们 rebase new-branch 时它即将改变 到主人身上:
# (master): git checkout new-branch
Switched to branch 'new-branch'
# (new-branch): git rebase master
file | 1 +
1 file changed, 1 insertion(+)
First, rewinding head to replay your work on top of it...
Applying: new file2
并且分支负责人不再具有相同的提交 ID,因为您已经 改变了系统的构建方式。
# (new-branch): git log --oneline --graph --all --decorate
* d9918d4 (HEAD, new-branch) new file2
* 3b3de88 (master) added b
* 9617f27 new file
现在,为了更好地阅读关于什么是真正的提交以及什么是对象的乐趣 在树上真的是,阅读The Git Objects网页。您将在短短几页中学到很多东西。
关于git - 为什么 git(有时)在 merge 时克隆提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25890990/