我为一些测试目的创建了一个额外的分支.
在开始工作之前,我切换回主分支,喝完茶后,我开始添加文件并修改master分支中的其他文件.
只有在我提交之后,我才记得我在主分支中,而在开始更改之前我必须切换到我的第二分支.
如果可以将此提交发送到第二个分支并从主分支中删除它,您能告诉我吗?
谢谢
如果我理解你,你可以做这样的事情:
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)
就这样.
这个问题的答案是"有点,但也许你不必".
要复制提交,请使用.这基本上告诉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.然后重命名master为branch,并将branch新名称重命名为master:
$ git branch -m branch temp
$ git branch -m master branch
$ git branch -m temp master
Run Code Online (Sandbox Code Playgroud)
第一步将标签更改branch为temp.第二个master改为branch(你仍然在上面,所以重写HEAD也是如此).最后一个更改temp为master,为您提供最初想要的提交DAG和标签设置.
与其他部分一样,您应该只在未发布(未推送)的提交上尝试这种"标签交换" .(这样做的原因很简单:当您发布提交时,您可以通过名称到提交ID映射来执行.如果您随机播放标签并"重新发布",则提交ID不会更改,但名称为-ID映射做的,所以任何人谁拿起你以前的广告,这master意味着bb71dde...例如,现在得到一个新的映射,是不是"快进相关的"老之一.人们,和git,预计分支映射改变,但通常只有"快进式".)
2例如,在Mercurial中,分支名称实际记录在commit-data中.