Ash*_*wat 2 git version-control
这可能吗 ?Cherry从其他分支中挑选到master分支的特定提交.例如:Say,我有两个分支:
-> master : <commit1>, <commit2>, <commit3>
-> test: <c1>, <c2>, <c3>, <c4>
Run Code Online (Sandbox Code Playgroud)
现在我想<c3>从test分支到<commit2>主分支中选择一个提交(例如:).
编辑:我知道可以通过rebase命令完成,但是只能通过命令完成cherry-pick吗?
tor*_*rek 14
你对Git的工作方式有一个根本性的错误.
这可能吗 ?Cherry从其他分支中挑选到master分支的特定提交.
不:Git 无法更改任何提交.您可以添加新提交,并且可以复制现有提交以从中进行新提交,即添加新提交,该提交是现有提交的副本(可能在副本中至少有一个不同的提交).后者是做什么的git cherry-pick.
您还可以更改任何分支名称为您记住的特定提交哈希ID .
说,我有两个分支:
Run Code Online (Sandbox Code Playgroud)-> master : <commit1>, <commit2>, <commit3> -> test: <c1>, <c2>, <c3>, <c4>
这不是绘制分支的好方法.这是一个更好的方法:
...--D--E--F--G <-- master
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
E这里的提交对应于你<commit1>,我只是使用单个字母来缩短它们.同样,F就像你的<commit2>,J就像你的<c3>.我还准备了另一个较早的承诺,D从其中两个分支延伸,表明有两种可能之前更早提交E和H.
请注意,每个提交都会记住其父提交:Gis 的父级F,因此我们说G"返回" F. F指回E,指回D,等等.同样,提交K点返回J哪些点返回I哪些点H.请注意,H仅在分支上test,也指向D.
(提交D特别有趣:它在两个分支上.这也是Git称之为两个分支的合并基础.但这不是我们关注的问题;它只是一个有趣的旁注,在Git中,提交可以超过一个分支同时.)
在这种情况下,分支名称指向一个特定的提交.这里的名称指向提交,名称指向提交.这就是我们如何决定哪些提交在哪些分支上:我们开始,就像Git那样,使用分支名称来查找分支提示.从那些提交提交,我们 - 或Git - 向后工作:我们从任何一个提交,到其父提交,然后到该提交的父级,依此类推.这个过程只有当我们厌倦了跟随父母(例如,退出)或被告知停止时才会停止 - 我们不会在这里看到 - 或者我们点击了根提交,这是一个没有父母的提交.您在存储库中进行的第一次提交是根提交,因为它没有可以用作父级的早期提交.(可以进行额外的root提交,但我们再也不会在这里看到了.)mastertestmasterGtestKgit log
现在我想
<c3>从测试分支到<commit2>主分支中挑选一个提交(例如:).
你可以挑选一个提交,但我用粗体斜体("提交")的部分是无稽之谈.采摘樱桃意味着复制提交.副本是一个新的提交,您通常会将其添加到分支.
由于你<c3>是我的J,让我们看看如果你使用会发生什么:
git checkout master
git cherry-pick test~1
Run Code Online (Sandbox Code Playgroud)
第一步让你"开启"分支master,即你现在添加的新提交将被添加到master,通过使名称master指向它们.
第二步J通过向后退一步来识别提交test.名称test标识提交K:分支名称"表示"该分支的提示提交.该~1后缀是指"算退一个父",所以我们从移动承诺K承诺J.这是我们要求Git复制的提交.
我们暂时忽略了执行此副本的确切机制,只看结果.Git做了一个"喜欢" 的新提交J; 让我们称之为新的提交J'.原始J副本和新副本之间存在一些差异J',目前重要的一点是副本的父级是现有的提示master,即提交G.所以J'回过头来看G.
完成复制后,J'永久存储新内容,Git会更新master以指向我们刚刚进行的新提交:
...--D--E--F--G--J' <-- master
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
请注意,不会影响现有提交.这是因为改变现有的提交几乎是不可能的.
我知道可以通过
rebase命令来完成...
它不能,这确实很重要.rebase的作用不是修改提交.相反,它制作副本 - 可能是很多副本.
让我们考虑一下您打开D-E-F-G序列的情况,master并且您希望在之前但之前复制J并插入它.也就是说,你想得到这个,即使这是不可能的: F G
...--D--E--F--J'-G <-- master
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
它是不可能的原因是G 无法改变,并G已经指出F.但是如果我们这样做了呢:
J'-G' <-- new-master
/
...--D--E--F--G <-- old-master
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
换句话说,如果我们复制的内容J到J'一个新的 new-master分支,与J'后到来F,然后复制G到G'与G'后到来J'?我们可以这样做git cherry-pick,我们只需要选择两个提交,J首先,然后G,到一个新的分支:
git checkout -b new-master master~1 # make the new-master branch at F
git cherry-pick test~1 # copy J to J'
git cherry-pick master # copy G to G'
Run Code Online (Sandbox Code Playgroud)
并且,假设一旦我们完成了这个,我们完全删除旧master名称,只需调用新名称master,如下所示:
J'-G' <-- master
/
...--D--E--F--G [abandoned]
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
现在,如果我们停止绘制废弃的原件G,并绘制master一条直线,看起来我们已插入和... J'之间...但我们没有:我们改为复制到.FGGG'
该git rebase命令本质上是一个自动化,高性能的"樱桃选择很多提交"命令,随后是一些分支名称在最后移动.
这只是事情的时候,但是无论什么时候这样做,是相当重要的很多.
假设我们从这开始,这很像以前,除了还有另一个分支:
...--D--E--F--G <-- master
\ \
\ L <-- develop
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
现在,让我们复制J到J',把那以后F,然后复制G到G'与J'作为G'的父,使名master记住新提交的哈希值ID G'.(这与我们之前做过的相同的rebase-copy一样;我们只有这个额外的develop分支.)
J'-G' <-- master
/
...--D--E--F--G
\ \
\ L <-- develop
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
现在让我们重新绘制一下,这样布局就不那么古怪了:
...--D--E--F--J'-G' <-- master
\ \
\ G--L <-- develop
\
H--I--J--K <-- test
Run Code Online (Sandbox Code Playgroud)
虽然我们得到了Git的"忘记"原有承诺G上master有利于崭新的G'具有J'作为其母公司,原来G还有分支develop.事实上,现在它看起来好像G是一直在develop和我们大概樱桃采摘成master从那里.
这里的关键点是你可以复制提交并忘记原件在那里,但如果是这样,你必须确保你真的忘记了它们. 如果这些原件在其他地方已知 - 通过您自己的存储库中的另一个分支,或者(更糟)git push编辑到另一个存储库 - 您必须让所有其他用户使用新版本,如果这是您想要的.您无法更改原件,只能将它们复制到新原件并让每个用户切换到新原件.
| 归档时间: |
|
| 查看次数: |
2918 次 |
| 最近记录: |