git - 为什么 git(有时)在 merge 时克隆提交?

标签 git github-for-windows

我知道有一些情况会导致 Git 提交被重复,例如 git cherry-pick。如果一个提交被精心挑选并“merge ”到另一个分支中,它会在提交图中出现两次,并带有两个提交哈希值。

Git 是否有可能在 git merge 操作期间重复提交?

我问的原因是以下提交图(在 TortoiseGit 中生成):

enter image description here

提交在此处以“日期顺序”(作者日期)列出。

在我在绿色分支(当时是我的 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/

相关文章:

git - git 中是否有 'p4 have' 等效项?

git - 查看 GitHub 为 Windows 客户端执行的命令

tortoisesvn - 如何在 GitHub for Windows 中过滤历史条目?

Github 显示新提交的空更改

git - 如何使用cmd创建文件?

git - 如何在忽略本地更改的同时进行 git pull?

git - perforce diff 到 git

git - 过滤存储库时如何保留标签?

git - 如何访问 Github for windows 上的一些命令

git - git push origin master 上出现错误 - 错误 : RPC failed; curl 56 SSL read: error:00000000:lib(0):func(0):reason(0), errno 10053 fatal: