你如何只推送一些本地 git 提交?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/604399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:13:41  来源:igfitidea点击:

how do you push only some of your local git commits?

gitversion-control

提问by ramanujan

Suppose I have 5 local commits. I want to push only 2 of them to a centralized repo (using an SVN-style workflow). How do I do this?

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

This did not work:

这不起作用:

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

That ends up pushing all 5 local commits.

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

I suppose I could do git reset to actually undo my commits, followed by git stash and then git push -- but I've already got commit messages written and files organized and I don't want to redo them.

我想我可以做 git reset 来实际撤消我的提交,然后是 git stash 然后是 git push ——但是我已经写了提交消息并组织了文件,我不想重做它们。

My feeling is that some flag passed to push or reset would work.

我的感觉是传递给 push 或 reset 的某些标志会起作用。

If it helps, here's my git config

如果有帮助,这是我的 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

回答by Ryan Graham

Assuming your commits are on the master branch and you want to push them to the remote master branch:

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

$ git push origin master~3:master

If you were using git-svn:

如果您使用的是 git-svn:

$ git svn dcommit master~3

In the case of git-svn, you could also use HEAD~3, since it is expecting a commit. In the case of straight git, you need to use the branch name because HEAD isn't evaluated properly in the refspec.

在 git-svn 的情况下,你也可以使用 HEAD~3,因为它期待提交。在直接 git 的情况下,您需要使用分支名称,因为在 refspec 中没有正确评估 HEAD。

You could also take a longer approach of:

您还可以采取更长的方法:

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

If you are making a habit of this type of work flow, you should consider doing your work in a separate branch. Then you could do something like:

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

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

Note that the "origin master:master" part is probably optional for your setup.

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

回答by Greg Hewgill

What I do is work on a local branch called "work". This branch contains all the temporary commits (like workarounds or private build options or whatever) that I don't intend to push to the upstream repository. I work away on that branch, then when I want to commit I switch to the master branch, cherry-pick the appropriate commits that I dowant to commit, then push master.

我所做的是在一个名为“工作”的本地分支上工作。该分支包含我不打算推​​送到上游存储库的所有临时提交(如解决方法或私有构建选项或其他任何内容)。我对那支离开工作,然后当我要提交我切换到主分支,樱桃挑选适当的提交,我希望提交,然后按主。

After pulling changes from the upstream into my master branch, I git checkout workand git rebase master. That rewrites all my local changes to be at the end of the history.

在将更改从上游拉入我的主分支后,我git checkout workgit rebase master. 这将我所有的本地更改都重写为历史记录的结尾。

I'm actually using git svnwith this workflow, so my "push" operation involves git svn dcommit. I also use tigwhich is a nice text mode gui repository viewer, to cherry-pick the appropriate commits to master.

我实际上正在使用git svn此工作流程,因此我的“推送”操作涉及git svn dcommit. 我还使用tigwhich 是一个不错的文本模式 gui 存储库查看器,来挑选适当的提交给 master。

回答by Thomas Leonard

By default, git-push pushes all branches. When you do this:

默认情况下,git-push 会推送所有分支。当你这样做时:

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

You move to a detached HEAD (you're not on any branch) and then you push all the branches, including the local master (which is still where it was) to the remote master.

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

The manual solution is:

手动解决方法是:

 git push origin HEAD:master

If you find the default behaviour of pushing all branches confusing (and dangerous!), add this to your ~/.gitconfig:

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

 [remote.origin]
    push = HEAD

Then only the branch you're on is pushed. In your example (a detached head), you would have got this error message, rather than accidentally pushing the wrong commits:

然后只有你所在的分支被推送。在您的示例(分离的头)中,您会收到此错误消息,而不是意外推送错误的提交:

 error: unable to push to unqualified destination: HEAD

回答by Tim

Short answer:

简短的回答:

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

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

Examples:

例子:

git push fc47b2

git push fc47b2

git push HEAD~2

git push HEAD~2

Long answer:

长答案:

Commits are linked together as a chain with a parent/child mechanism. Thus, pushing a commitactually also pushes all parent commitsto this commit that where not known to the remote. This is implicitly done when you git pushthe current commit: all the previous commits are also pushed because this command is equivalent to git push HEAD.

提交作为具有父/子机制的链链接在一起。因此,推送提交实际上也会将所有父提交推送到远程不知道的提交。这是在您git push当前提交时隐式完成的:所有先前的提交也被推送,因为此命令等效于git push HEAD.

So the question might be rewritten into How to push a specific commitand this specific commit might be HEAD~2, for example.

因此,问题可能会改写为如何推送特定提交,例如,此特定提交可能是 HEAD~2。

If the commits you want to push are non-consecutive, simply re-order them with a git rebase -ibefore the specific push.

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

回答by Yogesh Yadav

1) Use "git rebase" to reorder your commits, if you want to.

1) 如果需要,请使用“git rebase”重新排序您的提交。

git rebase -i

This command will display something like this in your editor ( I am using vim )

此命令将在您的编辑器中显示类似内容(我正在使用 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) Reorder your your commits according to your choice by simple cut paste. Suppose the new order is

2)根据您的选择通过简单的剪切粘贴重新排序您的提交。假设新订单是

pick 9781434 commitE

选择 9781434 commitE

pick c3d4961 commitC

选择 c3d4961 commitC

pick 4791291 commitA

选择 4791291 commitA

pick aa1cefc commitD

选择 aa1cefc commitD

pick a2bdfbd commitB

选择 a2bdfbd commitB

Make these changes in your editor and press ctrl+ O (writeOut)

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

Or you can also use

或者你也可以使用

git rebase -i HEAD~<commitNumber>

You can check the new sequence with

您可以检查新序列

git log

3) Now use

3)现在使用

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

If only one branch at remote(origin) and one at local(master), just use

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

git push <commit SHA>
git push aa1cefc

This will push commitB and commitD.

这将推动 commitB 和 commitD。