为什么git(有时)在合并时克隆一个提交?

时间:2014-09-17 12:46:50

标签: git github-for-windows

我知道有些情况导致Git提交被复制,例如git cherry-pick。如果提交被挑选并且"合并"进入另一个分支,它在提交图中出现两次,有两个提交哈希值。

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

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

enter image description here

提交列在' date-order'这里(作者日期)。

在我将efb916..提交到绿色分支(然后是我的master分支)后,我将绿色分支合并到红色分支(这是一个本地侧分支)。这在图表中显示为常规合并。到目前为止一切都很好。

之后,我点击了Github for Windows中的同步按钮,将我的本地master同步到远程origin/master。这从远程分支中提取了提交09067c..,然后合并或重新绑定了本地master,因此提交09067c..之后是提交efb916..。但是,不是真正合并 efb916..09067c..,而是Git重复提交efb916..并为重复提供新的哈希48e314..

最后,我的master指向48e314..(图中的黑色分支),我的本地分支指向68b78a..(红色分支)。提交efb916..48e314..的内容,日期,作者和消息完全相同。

这已经发生了好几次,有时只有一次提交被复制,有时会有几次提交。

为什么git会复制提交efb916..?我该如何预防呢?

编辑:作为补充说明:我发现我的master最初指向efb916..,但在Github同步efb916..之后不再发现,这很奇怪在master的提交历史记录中。

4 个答案:

答案 0 :(得分:3)

所以,我将首先将其分解为一个简单的视图。但它并不完全准确,但更容易掌握。然后,我将为您提供进一步阅读的资源。

简单视图

问题在于你对提交的真正含义感到困惑。提交哈希不是补丁的哈希值,它更像是整个系统的哈希值。因此,当您合并时,它在功能上应用您正在合并的两个(或更多)分支中的所有补丁,提出一个新的完整代码树,并在对象树中使用散列创建它。是现状的代表。

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

再次检查主人并在那里进行更改:

# (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

一个漂亮的树视图,有两个分支。注意的提交ID 新分支,因为它在我们改变新分支时即将发生变化 主人:

# (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

现在,为了好好阅读提交真正的内容,以及什么对象 在树真的是,读 Git 对象网页。你只需几页就能学到很多东西。

答案 1 :(得分:2)

  

然后合并或重新定位本地

它变了。当您重新设置时,您将创建重复的shas。合并时,您将创建一个合并提交。

您可以通过“拉动”来触发变基。几种不同的方式。您必须查看您的配置,以了解哪些适用于您的情况。

手动传递--rebase to pull

git pull --rebase

配置pull以默认执行rebase而不是合并(此设置可以在您的全局,repo或系统配置文件中)

git config pull.rebase true

然后另外在repo配置中可能存在每个分支设置,如

branch.<branch>.rebase true 

答案 2 :(得分:1)

git merge 永远不会重复提交,只会创建新的提交(合并提交)

git rebase 重复提交

git cherry-pick 重复提交

如果您不使用git rebase和git cherry-pick,您将确保历史记录中没有重复的提交 但我并不是说git rebase和git cherry-pick是坏命令,事实上,这些命令很棒!你唯一需要的就是如何使用它们

答案 3 :(得分:0)

在Github for Windows设置中找到它:

enter image description here