我有一些问题找到适合该工作的git命令。
我工作的地方目前正在切换源代码控制(TFVC - > Git)。但是,TFVC中的旧版本仍然需要不时修复错误。
我通过使用一些PowerShell脚本创建一个构建来确保我的“tfvc-merge”分支包含这些更改。
所以这就是我之后做的事情。
我试图画出来。所以基本上,拉取请求的空提交将在我的绘图中具有父级1和2。
我一直在寻找,几个小时没有找到正确的方法来做这件事。因此,提示可以指向正确的方向会很好。提前谢谢。
答案 0 :(得分:3)
我想你只想要git merge -s ours
。
Cherry挑选一些现有的提交会使没有链接回原始提交的新提交(新提交具有单个父提交;此提交是HEAD
提交时你跑了git cherry-pick
)。您所做的绘图显示了#em>两个父项的#2提交,就像您的樱桃选择是合并一样。因此,我不确定我是否正确了解情况本身。
短语空提交是Git本身使用的一个,但我发现它非常具有误导性:提交通常没有空的树对象(参见Is git's semi-secret empty tree object reliable, and why is there not a symbolic name for it? );使用git commit --allow-empty
进行提交的空白是该提交与其父级之间的差异。
有几种方法可以进行这样的提交,显然包括git commit --allow-empty
,但第一种方法不会进行 merge 提交。进行合并提交的唯一面向用户的命令是git merge
。如果这句话甚至意味着什么,这可能会让你遇到“合并而不合并”的问题。有时它会:git merge -s ours
。
(请注意,由于合并提交具有两个父项,因此使用短语“empty commit”来讨论此合并的含义甚至比讨论单父提交时更少。对于合并提交的两个父母,有两个差异。如果一个为空,另一个则不是。)
运行git merge
时,您可以提供合并策略名称。 Git有四个内置策略,名为recursive
,resolve
,octopus
和ours
。人们在正常合并期间遇到的正常问题是recursive
。 resolve
策略是-s recursive
的简化变体,几乎是相同的(两者仅在与多个合并基础合并的相对罕见的情况下不同)。 octopus
策略是Git在与 more 进行真正合并时使用的策略,而不是两个父母,我们在此不再讨论。留下-s ours
。在我们开始之前,让我们花一点时间来回顾正常(递归/解析)方法:
git checkout mainline
。git merge sidebranch
。此时,Git在mainline
的提示提交之间计算合并基础 - 分支名称指向的提交,我将其称为L
/ local / --ours
- 以及sidebranch
的提示,我将R
称为右/远程/ --theirs
:
...--o--*--o--L <-- mainline
\
o----R <-- sidebranch
合并基础是两个分支联合的点:这里,它是提交*
。从本质上讲,Git计算两个git diff
s:
git diff --find-renames <hash-of-base> <hash-of-L> # what we did
git diff --find-renames <hash-of-base> <hash-of-R> # what they did
Git然后尝试组合这两组更改,使这些组合更改适用于合并基础*
的内容,如果一切顺利,Git会创建一个新的< em> merge commit M
,其中L
为其第一个父级,R
为其第二个父级:
...--o--*--o--L--M <-- mainline
\ /
o----R <-- sidebranch
比较(差异)L
与M
将显示此合并从*
- vs - R
获得的更改,这些更改尚未在*
中-vs - L
。也就是说,我们开始了他们的工作。比较R
与M
将显示此合并从*
- vs - L
获得的更改,这些更改尚未在*
- vs - {{1 }}。也就是说,我们保持我们的工作。
R
策略 -s ours
做的很简单。 Git只保留-s ours
的树,而不是烦扰所有diff
。 Git使用L
作为其第一个父项进行新的合并提交,并将L
作为其第二个父项,因此图看起来完全相同:
R
但现在,如果我们运行...--o--*--o--L--M <-- mainline
\ /
o----R <-- sidebranch
来比较git diff mainline^1 mainline
和L
,则输出为空。如果我们运行M
来比较git diff sidebranch mainline
和R
,它们可能完全不同。 Git 完全忽略了提交M
的内容:它使用R
的内容M
。
如果你将空差异称为“空提交”,那么L
vs L
就是这样一个空提交。但是,作为此合并提交的一部分,仍然存在M
vs R
,因此如上所述,“空提交”这一短语在这里并不合理。
如果从旧tvfc分支到新分支的现有合并提交,整个事情会更有意义:
M
随着时间的推移变成:
...--o--M--o--<arbitrarily complex work>--I <-- integration
/
...--o--* <-- tvfc
在这种情况下,添加到 ...--o--M--o--<arbitrarily complex work>--I <-- integration
/
...--o--*--o--<arbitrarily complex work>-----X <-- tvfc
的所有新提交都可以简单地合并到tvfc
,integration
作为git checkout integration; git merge tvfc
和{{1}的合并基础现在提交integration
。 Git会将tvfc
与*
区分开来,看看他们发生了什么变化,并将其与*
vs X
结合起来,看看你发生了什么变化。在组合这些更改后,Git将进行新的合并提交*
,并且将来新的合并基础将是I
本身:
N
但这似乎不是你在做什么。如果您现在只是设置这种情况,我想知道一点。如果是这样,上面的X
命令可能就是你想要的。