将最近的提交转移到另一个分支

rah*_*man 5 git

我为一些测试目的创建了一个额外的分支.

在开始工作之前,我切换回主分支,喝完茶后,我开始添加文件并修改master分支中的其他文件.

只有在我提交之后,我才记得我在主分支中,而在开始更改之前我必须切换到我的第二分支.

如果可以将此提交发送到第二个分支并从主分支中删除它,您能告诉我吗?

谢谢

use*_*113 8

如果我理解你,你可以做这样的事情:

git checkout master
git log
now check hash commit you want to move - for example: 0123456
git checkout branch
git cherry-pick 0123456
git checkout master
git revert 0123456
Run Code Online (Sandbox Code Playgroud)

就这样.


tor*_*rek 6

这个问题的答案是"有点,但也许你不必".

复制提交,请使用.这基本上告诉git:"看看我要求你挑选的提交.无论它做了什么更改,在当前分支上再次进行相同的更改.然后使用相同的提交消息进行新的提交1. "git cherry-pick commit

因此,如果您已经提交了一个提交master,那么您需要提交它newbranch:

$ git checkout newbranch
$ git cherry-pick master
Run Code Online (Sandbox Code Playgroud)

此时,您将处于启用状态,newbranch并且将复制提交.您现在需要对旧提交执行某些操作master.

如果你没有在任何地方发布(推送,或让别人拉)这个提交,你只需要"回滚":

$ git checkout master
$ git reset --hard HEAD^  # be careful here! I always run "git status" first
Run Code Online (Sandbox Code Playgroud)

请注意,git reset --hard将删除任何正在进行的工作.

如果您发布提交,则通常应该将其还原(请参阅user2699113的答案)."revert"很像一个樱桃选择,复制提交,除了它反转更改:添加的任何内容然后现在被删除,并且删除的任何内容都会被添加回来.(并且,与cherry-pick一样,revert将自动提交,除非你告诉它不要.)

(请注意,您可以通过SHA-1 ID指定提交,但如果有名称分支或标记名称或其他引用名称,则可以只写入名称.)


1除非您使用-n--no-commit禁止它,否则git无法进行相同的更改并告诉您存在冲突并让您自己修复它.


关于"也许你没有必要"的部分是什么?

这是关于git及其提交和分支的事情.Git与大多数其他版本控制系统不同,因为当您在"分支"上执行提交时,分支名称实际上不是提交的一部分.2 指定分支名称(或标签,无论您想要调用它们),但实际的分支结构 - "结构分支" - 由每个提交的历史记录形成.

提交时,该提交记录其父提交.分支名称只是标签,它为您(和git)提供了一个起始位置,然后git跟随提交父ID.这意味着我们可以手工绘制提交图(有向无环图或提交的DAG):

A <-- B <-- C     <-- master
            ^
             \
              D   <-- branch
Run Code Online (Sandbox Code Playgroud)

这里提交D是分支的提示branch,它指回提交C作为其父.提交C点返回B,指向A,这是初始(root,parent-less)提交.

当你在"分支大师"上并创建一个新分支时,它只会创建一个指向您现在所在位置的新标签.所以假设你已经A通过了C(这次我不会用尽可能多的箭头绘制它们;只是假设箭头通常指向左侧):

A - B - C      <-- HEAD=master
Run Code Online (Sandbox Code Playgroud)

这次我添加了HEAD=以显示git如何跟踪你所在的分支.(HEAD目录中的.git文件只包含分支的名称:cat .git/HEAD你通常会看到ref: refs/heads/master或者其他什么.)如果你现在这样做了git checkout -b branch:

A - B - C      <-- master, HEAD=branch
Run Code Online (Sandbox Code Playgroud)

(现在.git/HEAD包含branch而不是master).

当你进行新的提交(任何新提交,包括来自cherry-pick和revert的提交)时,git HEAD会查看你所在的分支,以及该分支对其SHA-1 ID的影响.这就是"分支的一角".然后Git进行一个新的提交,其父级是旧的分支提示,并将新的提交ID写入分支文件,以便分支名称指向新的提交.(当然HEAD,它仍然只有分支名称.)

所以,如果你是"在分支上branch"并进行新的提交D,这就是你得到的:

A - B - C      <-- master
          \
            D  <-- HEAD=branch
Run Code Online (Sandbox Code Playgroud)

如果你稍微改了一下,并且"在分支上master",你会得到这个:

A - B - C      <-- branch
          \
            D  <-- HEAD=master
Run Code Online (Sandbox Code Playgroud)

但等等,这只是你想要的,除了分支标签.你需要做的就是让名称master指向哪里branch,branch指向哪里master,并切换,HEAD以便它branch代替master.

事实证明,这很容易......好吧,非常简单.:-)你需要一个临时名称,因为git不会让你有两个同名的分支.首先,重命名分支branch以让您更改master.然后重命名masterbranch,并将branch新名称重命名为master:

$ git branch -m branch temp
$ git branch -m master branch
$ git branch -m temp master
Run Code Online (Sandbox Code Playgroud)

第一步将标签更改branchtemp.第二个master改为branch(你仍然在上面,所以重写HEAD也是如此).最后一个更改tempmaster,为您提供最初想要的提交DAG和标签设置.

与其他部分一样,您应该只在未发布(未推送)的提交上尝试这种"标签交换" .(这样做的原因很简单:当您发布提交时,您可以通过名称到提交ID映射来执行.如果您随机播放标签并"重新发布",则提交ID不会更改,但名称为-ID映射做的,所以任何人谁拿起你以前的广告,这master意味着bb71dde...例如,现在得到一个新的映射,是不是"快进相关的"老之一.人们,和git,预计分支映射改变,但通常只有"快进式".)


2例如,在Mercurial中,分支名称实际记录在commit-data中.