git:推送单个提交,使用 rebase 重新排序,重复提交

git: Pushing Single Commits, Reordering with rebase, Duplicate Commits

我想将多个单个提交推送到 git 远程仓库。我按照杰夫在这里找到的答案这样做:

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 拉取,我的日志中会出现重复提交,例如:

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

所以我发布了这个问题:

Roger 的回答让我想到了这个问题:为什么我在变基和拉动后看到重复提交?

从上面看,rebase 之前的日志如下所示:

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

rebase 后的日志如下所示:

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而是复制它们。 Git 通常会隐藏原件,但如果您的原件包含其他用户共享的那些,您(当然还有他们)仍然会看到这些原件。

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

在这种情况下,您所做的是变基(即复制)他们的 提交以及您自己的提交。部分问题源于使用 git pull,这意味着 "fetch then merge",而您想要的是 "fetch then rebase"。您可以单独执行以下步骤:

git fetch
git rebase

或使用git pull --rebase:

git pull --rebase

它告诉 pull 脚本在执行提取后,它应该执行变基而不是合并。您还可以将 git 配置为自动执行此操作,而无需 --rebase 参数。2

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


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

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