我知道有些情况导致Git提交被复制,例如git cherry-pick
。如果提交被挑选并且"合并"进入另一个分支,它在提交图中出现两次,有两个提交哈希值。
Git是否可能在git merge
操作期间重复提交?
我问的原因是以下提交图(在TortoiseGit中生成):
提交列在' 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
的提交历史记录中。
答案 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设置中找到它: