如何只推送部分本地 git 提交?

假设我有5个本地提交。我只想将其中的2个推送到一个集中的回购(使用 SVN 风格的工作流)。我该怎么做?

这种做法没有奏效:

git checkout HEAD~3  #set head to three commits ago
git push #attempt push from that head

最终将推动所有5个本地提交。

我想我可以做 git 重置来实际撤消提交,然后是 git 存储,然后是 git 推送——但是我已经写好了提交消息,组织好了文件,我不想重做它们。

我的感觉是,一些国旗通过推动或重置将工作。

如果有帮助的话,这是我的 git 配置

[ramanujan:~/myrepo/.git]$cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = ssh://server/git/myrepo.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
85364 次浏览

我在当地一家叫“工作”的分公司工作。这个分支包含所有我不打算推送到上游存储库的临时提交(比如工作区或私有构建选项等等)。我在那个分支上工作,然后当我想提交时,我切换到主分支,挑选我 想提交的适当提交,然后推主分支。

在将更改从上游拉入到我的主分支之后,I git checkout workgit rebase master。这将改写我所有的局部变化,使之成为历史的终结。

我实际上在这个工作流中使用的是 git svn,所以我的“推送”操作涉及到 git svn dcommit。我还使用了 tig,它是一个很好的文本模式 gui 存储库查看器,以挑选合适的提交来掌握。

假设您的提交在主分支上,并且您希望将它们推送到远程主分支:

$ git push origin master~3:master

如果您使用的是 git-svn:

$ git svn dcommit master~3

在 git-svn 的情况下,您还可以使用 HEAD ~ 3,因为它需要提交。在使用直接 git 的情况下,需要使用分支名称,因为在 refspec 中没有正确地计算 HEAD。

你也可以采取更长期的方法:

$ git checkout -b tocommit HEAD~3
$ git push origin tocommit:master

如果你正在养成这种工作流的习惯,你应该考虑在一个单独的分支中完成你的工作。然后你可以这样做:

$ git checkout master
$ git merge working~3
$ git push origin master:master

请注意,对于您的设置,“ Originmaster: master”部分可能是可选的。

默认情况下,git-push 推送所有分支:

 git checkout HEAD~3  #set head to three commits ago
git push #attempt push from that head

您移动到一个分离的 HEAD (您不在任何分支上) ,然后将所有分支,包括本地主机(它仍然在原来的位置)推送到远程主机。

手动解决方案是:

 git push origin HEAD:master

如果您发现推动所有分支的默认行为令人困惑(并且很危险!) ,请将下面的代码添加到 ~/. gitconfig:

 [remote.origin]
push = HEAD

那么只有你所在的树枝才会被推动。在您的示例(一个分离的头)中,您将得到这个错误消息,而不是意外地推出错误的提交:

 error: unable to push to unqualified destination: HEAD

1)如果愿意,可以使用“ git rebase”重新排序提交。

git rebase -i

这个命令将在您的编辑器中显示类似的内容(我正在使用 vim)

pick 4791291 commitA
pick a2bdfbd commitB
pick c3d4961 commitC
pick aa1cefc commitD
pick 9781434 commitE


# Rebase ..............
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out








^G Get Help         ^O WriteOut         ^R Read File        ^Y Prev Page                ^K Cut Text         ^C Cur Pos
^X Exit             ^J Justify          ^W Where Is         ^V Next Page            ^U UnCut Text       ^T To Spell

2)根据你的选择重新排序你的提交。假设新的顺序是

选择9781434委员会

选择 c3d4961

选4791291委员会

选一个

选择委员会

在编辑器中进行这些更改,然后按 ctrl + O (writeOut)

或者你也可以用

git rebase -i HEAD~<commitNumber>

你可以用

git log

3)现在使用

git push <remoteName> <commit SHA>:<remoteBranchName>

如果只有一个分支在远程(原点)和一个在本地(主) ,只需使用

git push <commit SHA>
git push aa1cefc

这将推动委员会和委员会。

简短的回答:

git push <latest commit SHA1 until you want commits to be pushed>

例子:

git push origin fc47b2:master

git push origin HEAD~2:main

长话短说:

提交作为具有父/子机制的链连接在一起。因此,推动一个承诺实际上也将 所有父级提交推送到远程不知道的提交。这是在 git push当前提交时隐式执行的: 所有以前的提交都被推送,因为这个命令等效于 git push HEAD

因此问题可能被重写到 如何推动特定的提交中,这个特定的提交可能是 HEAD ~ 2,例如。

如果您想推送的提交是非连续的,只需在 特定的推力之前用 git rebase -i重新排序它们。