如何将特定提交推送到远程,而不是以前的提交?
Posted
技术标签:
【中文标题】如何将特定提交推送到远程,而不是以前的提交?【英文标题】:How can I push a specific commit to a remote, and not previous commits? 【发布时间】:2011-03-14 21:23:05 【问题描述】:我已经对不同的文件进行了多次提交,但到目前为止,我只想将特定的提交推送到我的远程存储库。
这可能吗?
【问题讨论】:
git: push a single commit 的可能重复项 在这里查看好的技术:***.com/a/1789142/1579667 【参考方案1】:要推动通过一个给定的提交,你可以这样写:
git push <remotename> <commit SHA>:<remotebranchname>
如果<remotebranchname>
已经存在于遥控器上。 (如果没有,您可以使用git push <remotename> <commit SHA>:refs/heads/<remotebranchname>
自动创建它。)
如果你想推送一个提交而不推送之前的提交,你应该首先使用git rebase -i
重新排序提交。
【讨论】:
git push <remotename> <commit SHA>:<remotebranchname>
有效。诀窍是将它与git rebase -i
结合起来移动你想要的提交作为第一个提交,并指定commit-sha
另一个好技巧是确保复制要推送的提交的SHA
请记住,如果远程分支尚不存在,则会失败。可以使用git push <remotename> <commit SHA>:refs/heads/<new remote branch name>
创建分支。在此之后,按照答案描述推送。
例如,用一些标准名称推送除最后一次提交之外的所有内容git push origin HEAD~1:master
。
另外请注意,如果您已经将稍后的 SHA 推送到该远程分支,那么您将需要强制推送这个。使用-f
标志。【参考方案2】:
重新排序描述中缺少其他答案。
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
将单个提交推送到我的远程主分支。
参考资料:
-
http://blog.dennisrobinson.name/push-only-one-commit-with-git/
http://blog.dennisrobinson.name/reorder-commits-with-git/
另见:
-
git: Duplicate Commits After Local Rebase Followed by Pull
git: Pushing Single Commits, Reordering with rebase, Duplicate Commits
【讨论】:
似乎有些起源可能不允许这样做。例如,在 GitLab 中,我看到“您不允许将代码强制推送到此项目的受保护分支。”。这有点奇怪,因为我不认为我在强迫任何事情,只是在做一个正常的推动。知道如何在不“强迫”的情况下做到这一点吗? @Ed 不需要强制推送。听起来您的特定 git 设置有问题。也许您重新设置了远程 HEAD 提交的基础?我不知道受保护的分支是什么,听起来像是权限问题。 Samuel - 这是有道理的,但 git rebase -i 只向您显示晚于远程 HEAD 的本地提交,所以我不知道我该怎么做。 Samuel - 实际上我现在可以进行部分推送,所以我不知道出了什么问题,但它一定是在尝试以一种或另一种方式推送不是从远程 HEAD 派生的提交。 @Ed 您说“git rebase -i 只向您显示晚于远程 HEAD 的本地提交”,我认为这不是真的。我进行了测试,并且能够通过远程 HEAD 重新定位。【参考方案3】:我建议使用git rebase -i
;将您要推送的提交移到您所做的提交的顶部。然后使用git log
获取rebased 提交的SHA,检查出来,然后推送。变基将确保您所有其他提交现在都是您推送的提交的子项,因此未来的推送也可以正常工作。
【讨论】:
你能不能给出一个完整的例子,尤其是。重新git log
步骤?
假设您有 3 个相对独立的提交,消息“A”、“B”、“C”按该顺序提交,并且您想要推送“B”。 'git rebase -i' 应该让你和编辑列出所有三个;向上移动 B 并保存/退出。 'git log --pretty=oneline -n3' 将在每条消息之前列出 B、A、C 和散列,B 现在在最后。 'git checkout -b temp $hash_of_B; git push' 应该在那时推动 B。然后你可能想要'git checkout -b master; git branch -d temp' 回到你以前的状态,假设你在你的本地主分支上;根据需要替换。
+1 你在 rebase-push-rebase 之后遇到过"wrath of the git gods" 吗? (也有可能是偶然发生的,对吧?)
如果您仔细阅读我的回答,您会发现推送仅发生在变基 之后,并且变基提交仅移动到尚未推送的其他提交之上。一旦提交被推送,它通常应该被认为是一成不变的;在未来的变基中不要管它。这种技术只是为了让您可以在推送它们之前将多个本地更改整理成一个良好的顺序。如果您的跟踪设置正确,没有其他参数的“git rebase -i”将默认甚至不显示您推送的提交,因此它比其他一些方法更安全。【参考方案4】:
与所有其他方法相比,Cherry-pick 在推送特定提交时效果最好。
这样做的方法是:
创建一个新分支 -
git branch <new-branch>
使用您的原始分支更新您的新分支 -
git fetch
git rebase
这些操作将确保您拥有与您的来源完全相同的东西。
Cherry-pick你想要推送的sha id
-
git cherry-pick <sha id of the commit>
你可以通过运行得到sha id
git log
将其推送到您的原点 -
git push
运行 gitk
以查看一切是否与您想要的一样。
【讨论】:
使用git rebase -i
将是上述解决方案中建议的理想解决方案。只有在您想要复制提交时才必须使用 Cherry pick。【参考方案5】:
我相信你必须“git revert”回到那个提交然后推送它。或者您可以cherry-pick
提交到一个新分支,然后将其推送到远程存储库上的分支。比如:
git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin branch
【讨论】:
git revert 在这里是个坏主意——它会创建一个新的提交 @hasen:然后你可以cherry-pick
你想要的提交。
revert 和cherry-pick 都是坏主意。 git rebase -i 是你的朋友,请参阅下面 Walter Mundt 的回答。
@Nicolas,为什么挑选樱桃是个坏主意?
@Antoine,通常您希望您的分支与它在源上跟踪的分支保持同步。如果你挑选,你正在做一个复制/粘贴,你必须在某个时候处理未推送的副本。如果你 rebase -i,你做“剪切和粘贴”,并保持你的分支与远程同步到你想要的位置。【参考方案6】:
最简单的方法是使用两个命令。
首先,让本地目录进入你想要的状态。那么,
$ git push origin +HEAD^:someBranch
仅在远程而不是本地从someBranch
中删除最后一次提交。您可以连续执行几次,或更改 +HEAD^
以反映您希望从远程批量删除的提交数。现在你重新站起来,使用
$ git push origin someBranch
照常更新遥控器。
【讨论】:
【参考方案7】:您也可以在另一个目录中:
git clone [你的仓库] 用您刚刚克隆的存储库的 .git 目录覆盖原始存储库中的 .git 目录。 git add 和 git commit 你原来的【讨论】:
【参考方案8】:我确实想忘记一段古老的大历史,并从我选择的新提交开始:
rsync -a --exclude '.git' old-repo/ new-repo/
cd new-repo
git push
当现在旧仓库更改时,我可以将补丁应用到新仓库,以将它们重新定位到新仓库。
【讨论】:
以上是关于如何将特定提交推送到远程,而不是以前的提交?的主要内容,如果未能解决你的问题,请参考以下文章