如何将特定的提交推送到远程而不是先前的提交?


Answers:


1086

为了推动通过了一个指定的提交,你可以这样写:

git push <remotename> <commit SHA>:<remotebranchname>

提供的内容<remotebranchname>已存在于遥控器上。(如果没有,您可以使用git push <remotename> <commit SHA>:refs/heads/<remotebranchname>它来自动创建。)

如果要在推动先前提交的情况下推送提交,则应首先使用git rebase -i来重新排序提交。


66
git push <remotename> <commit SHA>:<remotebranchname>作品。诀窍是将其与git rebase -i移动所需的提交一起作为第一个提交,并指定commit-sha
dminer 2012年

29
另一个不错的技巧是确保您执行rebase -i之后而不是在此之前复制要推送的提交的SHA ,就像我刚才所做的一样:)
estan

33
请记住,如果远程分支尚不存在,则此操作将失败。可以使用创建分支git push <remotename> <commit SHA>:refs/heads/<new remote branch name>。之后,按答案描述进行推送。
Wes Oldenbeuving 2012年

31
例如,使用最后一个标准名称推送除最后一次提交以外的所有内容git push origin HEAD~1:master
无声的噪音,

3
另请注意,如果您已经将更高版本的SHA推送到该远程分支,则需要强制推送此SHA。使用-f标志。
伊恩·沃恩

79

重新排序说明中缺少其他答案。

git push <remotename> <commit SHA>:<remotebranchname>

会推送一次提交,但该提交必须是您本地的非推送提交中最古老的提交,不要与顶部提交,第一提交或技巧提交混淆,在我看来,这些都是模棱两可的描述。提交需要使用最旧的提交,即距最新提交最远的提交。如果不是最旧的提交,则将推送从最旧的,本地的,未推送的SHA到指定的SHA的所有提交。要重新排列提交,请使用:

git rebase -i HEAD~xxx

重新排序提交后,您可以安全地将其推送到远程存储库。

总结一下,我用

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

将单个提交推送到我的远程主分支。

参考文献:

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

也可以看看:

  1. git:本地重新设置后重复提交,后跟拉
  2. git:推送单次提交,使用重新设置基准重新排序,重复提交

3
看来,某些起源可能不允许这样做。例如,在GitLab中,我看到“不允许您将推送代码强制到该项目上的受保护分支。” 这有点奇怪,因为我认为我没有强迫任何东西,只是做了正常的推动。知道如何在没有“强制”的情况下进行操作吗?
Ed Avis

1
@Ed Shoud不需要强行推动。听起来您的特定git设置有问题。也许您已根据远程HEAD提交重新定位了?我不知道什么是受保护的分支,听起来像是权限问题。
塞缪尔

1
Samuel-很有道理,但是git rebase -i仅向您显示本地提交,该提交晚于远程HEAD,因此我不知道该怎么做。
Ed Avis

1
塞缪尔(Samuel)-实际上,我现在可以进行部分推送,所以我不知道出了什么问题,但是它一定一直在尝试以某种方式推送不是从远程HEAD派生的提交。
Ed Avis

1
@Ed您说过“ git rebase -i仅向您显示本地提交,该本地提交晚于远程HEAD”,我认为这不是真的。我进行了测试,并能够通过远程HEAD重新定位。
塞缪尔

25

我建议使用git rebase -i; 将您要推送的提交移动到所做的提交的顶部。然后使用git log获取重新提交的提交的SHA,将其检出并推送。重新设置将确保您所有其他提交现在都是您推送的子提交,因此将来的推送也可以正常工作。


3
您能否举个完整的例子,尤其是。再走git log一步?
Drux

4
假设您有3个相对独立的提交,并按该顺序提交了消息“ A”,“ B”,“ C”,并且您要推送“ B”。'git rebase -i'应该让您和编辑者列出所有这三个;向上移动B并保存/退出。'git log --pretty = oneline -n​​3'将在每条消息之前列出带有散列的B,A,C,现在B排在最后。'git checkout -b临时$ hash_of_B; git push'应该在那个时候推送B。然后,您可能需要'git checkout -b master; git branch -d temp'返回到以前的状态,假设您在本地master分支上;视情况更换。
Walter Mundt 2013年

1
+1您是否在rebase-push-rebase之后遇到过“ git神的愤怒”?(可以想像也可能是偶然发生的,对吧?)
Drux

2
如果仔细阅读我的回答,您会看到推送仅在重新设置基准之后发生,并且已重新设置基准的提交仅移至尚未推送的其他提交之上。一旦推动提交,通常应将其视为固定的。别管它,以备将来重新定标。这项技术只是为了使您可以在推送之前将多个本地更改分类为一个良好的顺序。如果您已正确设置跟踪,则没有其他参数的'git rebase -i'将默认不显示推送的提交,因此比其他方法更安全。
Walter Mundt 2014年

21

在推送特定提交时,Cherry-pick与所有其他方法相比效果最好。

这样做的方法是:

创建一个新分支-

git branch <new-branch>

使用origin分支更新新分支-

git fetch

git rebase

这些操作将确保您拥有与原籍完全相同的资料。

樱桃选择sha id您要执行的操作-

git cherry-pick <sha id of the commit>

您可以sha id通过运行获得

git log

将其推到您的原点-

git push

运行gitk以查看一切看起来都与您想要的方式相同。


2
git rebase -i如上述解决方案所建议,使用将是理想的解决方案。仅当您要复制提交时才必须使用Cherry Pick。
Vinay Bhargav 2015年

13

我相信您将必须“ git revert”回到该提交,然后再推送它。或者,您可以cherry-pick提交到新分支,然后将其推送到远程存储库上的分支。就像是:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}

9
git revert在这里是个坏主意-它创建了一个新的提交
hasen

1
@hasen:然后,您可以只是cherry-pick所需的提交。
乔什(Josh K)2010年

4
恢复和选择都是不好的主意。git rebase -i在这里是您的朋友,请参见下面的Walter Mundt的答案。
尼古拉斯C

3
@Nicolas,为什么挑选樱桃是个坏主意?
Antoine 2014年

3
@Antoine,通常情况下,您希望分支与其原始跟踪的分支保持同步。如果您选择“领料”,则说明您正在执行复制/粘贴操作,并且在某些时候您将不得不处理未推送的副本。如果对-i重新设置基础,则将执行“剪切和粘贴”操作,并使分支与远程服务器保持同步,直到您希望的位置为止。
Nicolas C

0

您还可以在另一个目录中:

  • git clone [您的存储库]
  • 用您刚才克隆的存储库的.git目录覆盖原始存储库中的.git目录。
  • git add和git提交您的原始文件
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.