git:推送单一提交,重新排序,重复提交

时间:2015-01-05 18:26:16

标签: git duplicates git-rebase git-pull

我想将几个单一提交推送到git远程仓库。我跟着Geoff在这里找到的答案:

How can I pushing specific commit to a remote, and not the previous commits?

我想推送的提交不在头,所以我必须首先使用rebase对提交进行重新排序,然后我使用这些指令来执行此操作:

http://gitready.com/advanced/2009/03/20/reorder-commits-with-rebase.html

基本上我已经完成了:

git clone
git commit
git commit
...
git pull
git rebase -i HEAD~3
git push origin <SHA>:master

我这样做有错误。所以我开始深入研究这个问题。我发现在我的日志中有重复的提交,如果我在变基后进行第二次git pull,例如:

git clone
git commit
git commit
...
git pull
git log --pretty=format:"%h - %an : %s" // log before rebasing
git rebase -i HEAD~3
git pull
git log --pretty=format:"%h - %an : %s" // log after rebasing
git pull 
git log --pretty=format:"%h - %an : %s" // log after rebasing after pulling

所以我发布了这个问题:

git: Duplicate Commits After Local Rebase Followed by Pull

Roger在那里的回答让我想到了这个问题:为什么我在重新定位和拉动后会看到重复的提交?

从上面看,重新定位之前的日志如下所示:

84e4015 - Me : Local Commit 3
0dbe86a - Me : Local Commit 2
d57ba2a - Me : Merge branch 'master' of remote repository
a86ea35 - Me : Local Commit 1 before reordering
2fc4fe7 - Remote User 2 : Remote Commit 2
b7a8656 - Remote User 1 : Remote Commit 1
8ce80fc - Me : Merge branch 'master' of remote repository

变基后的日志如下:

cf1ff7b - Me : Local Commit 3
cd14463 - Me : Local Commit 2
b9d44fb - Me : Local Commit 1 after reordering
9777c56 - Remote User 2 : Remote Commit 2
a2d7d8b - Remote User 1 : Remote Commit 1
8ce80fc - Me : Merge branch 'master' of remote repository

请注意原始2提交2fc4fe7和b7a8656有新的SHA; 9777c56和a2d7d8b。我相信这是问题的开始。

现在,在我执行另一个git之后,日志看起来像这样:

e8e1a85 - Me : Merge branch 'master' of remote repository
cf1ff7b - Me : Local Commit 3
cd14463 - Me : Local Commit 2
b9d44fb - Me : Local Commit 1 after reordering
9777c56 - Remote User 2 : Remote Commit 2
a2d7d8b - Remote User 1 : Remote Commit 1
2fc4fe7 - Remote User 2 : Remote Commit 2 // duplicate 2
b7a8656 - Remote User 1 : Remote Commit 1 // duplicate 1
8ce80fc - Me : Merge branch 'master' of remote repository

请注意,远程提交现在已重复,并且远程提交的原始SHA(2fc4fe7和b7a8656)已返回。

在Roger的回应中,他说这看起来像是其他人推动git的错,而且他们正在重新调整他们已经推动的提交。但是我认为在本地重新推动推送提交是我的错。

这是因为我重新设定了已被推送到遥控器的提交吗?如果是这样,我应该怎么做才能避免这种情况?我需要重新提交我的提交,以便我可以推送一个提交。我应该使用分支系统吗?如果是这样,我将如何使用分支来解决这个问题?

1 个答案:

答案 0 :(得分:1)

简短的回答是,rebase不会更改提交, 1 ,而是复制它们。 Git通常会隐藏原件,但如果您的原件包含其他用户共享的原件,您(当然还有他们)仍会看到原件。

作为一般规则,您应该只修改自己的私有,未发布的提交。由于没有人 else 根据定义拥有这些副本,因此您制作自己的副本然后(通过rebase)隐藏原件并不是问题:您现在可以看到您的副本而不是您的副本原件,没有其他人看到,如果需要你可以继续改造。但是,一旦您发布(通过push或类似)提交,您就不能再更改它,因为其他人现在拥有您原始的副本,包括其SHA-1 ID,他们仍然会有它以后。

在这种情况下,您所做的是重新设置(即复制)他们的提交以及您自己的提交。部分问题源于使用git pull,这意味着“fetch then merge”,当你想要的是“fetch then rebase”时。您可以单独执行这些步骤:

git fetch
git rebase

或使用git pull --rebase

git pull --rebase

告诉pull脚本在执行获取后,它应该执行rebase而不是合并。您还可以配置git以自动执行此操作,而不使用--rebase参数。 2

现在的主要问题是你有一个你可能不想要的合并。如果是这样,您将需要“撤消”该合并(使用git reset;请参阅其他stackoverflow帖子。)


1 它不能:git对象(包括提交)由其对象ID命名,该对象ID是其内容的加密校验和。提交由其父ID,树的ID,提交的作者和提交者(名称,电子邮件和时间戳)以及提交消息组成。如果您更改其中任何一项,您将获得一个具有不同ID的新的不同提交。

2 您甚至可以将其配置为使用git pull --rebase=preserve。但是,在rebase操作之间保留合并是一个单独的主题(我之前在stackoverflow发布中已经介绍过了)。