git - 列出源分支中冲突文件路径的命令是什么
问题描述
当我尝试将 a 合并source branch
为target branch
时,git 识别出两个文件存在冲突。但是这两个文件都对应着不同的文件路径source branch
和target branch
(文件已被移动和修改)。我需要在source branch
.
请注意,我可以git diff --name-only --diff-filter=U
用来列出合并冲突下的文件,但这会列出目标分支中的路径(因为我签target branch
出并拉source branch
入其中)。
是否有命令列出源分支中冲突文件的路径?
解决方案
当我尝试将“源分支”合并到“目标分支”时,git 识别出两个文件存在冲突。但是这两个文件对应“源分支”和“目标分支”中的不同文件路径(文件已被移动和修改)。
更具体地说,我相信你做到了:
git checkout tgtbranch
git merge srcbranch
并得到:
CONFLICT (rename/delete): orig-filename deleted in HEAD and renamed
to new-filename in A. Version A of new-filename left in tree.
Automatic merge failed; fix conflicts and then commit the result.
(请注意,我使用名为A
andB
而不是srcbranch
and的分支tgtbranch
分别复制了此冲突。此外,CONFLICT
消息都在一行上。我将其分成两部分仅用于发布目的。)
我需要在“源分支”中获取这个冲突文件的路径。
从上面可以看出,此信息在打印的消息中可用。CONFLICT
git merge
不幸的是,这些信息在之后的任何地方都无法获得,至少不能直接获得。您必须保存消息。(如果您没有保存消息,请参阅下面的另外两个替代方案。)CONFLICT
CONFLICT
可用的是打印git status
的内容:
$ git status --short
UA new-filename
$ git status
On branch B
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
added by them: new-filename
no changes added to commit (use "git add" and/or "git commit -a")
此时我们还可以使用git ls-files --stage
来查看 Git索引中的内容:
$ git ls-files --stage
100644 4466f6b253fc4b67ec2749befdd29b7c1f573e36 0 README
100644 923932af0c5b6ddc43c116c648cd793759949b66 3 new-filename
只有新的文件名存在!
如果您没有保存CONFLICT
线路,您可以做什么
方法一:重复合并
一种可能是最简单的选择是重复合并。当然,如果您正在解决合并问题,您可能不想弄乱当前索引和您的工作树,这使得这有点棘手。你可以:
- 克隆存储库,以便您拥有一个具有新索引和工作树的新克隆,或者
- 使用
git worktree add
,只要你有git worktree
然后在新的克隆或工作树中重新合并。用于git checkout
检查tgtbranch
原始克隆(如果您重新克隆)或当前克隆(如果您正在使用git worktree
)中的哪些点的提交,然后运行git merge
以将提交合并到tgtbranch
原始克隆中的哪些点(如果您重新克隆)或当前克隆(如果您正在使用git worktree
)。那是:
$ git rev-parse tgtbranch
<hash>
$ git rev-parse srcbranch
<hash>
$ cd /tmp && git clone <path> reclone && cd reclone
$ git checkout <hash> && git merge <hash>
如果您正在使用重新克隆程序,或者:
$ git worktree add --detach <path> tgtbranch
$ cd <path> && git merge srcbranch
如果您正在使用该git worktree
方法。
此合并将吐出CONFLICT
线。保存!然后删除新的克隆或添加的工作树——它的全部目的是获取CONFLICT
行。您的问题现已解决:您拥有原始文件名。
方法2:git diff
针对合并基础使用
合并操作在using中检测到重命名。重命名查找的阈值设置为您随参数提供的任何值,如果您未指定数字,则设置为 50%。tgtbranch
git diff --find-renames
-X find-renames=number
这git diff
是两个特定提交之间的差异:Git 自动找到的合并基础提交,以及tgtbranch
或的提示提交srcbranch
(无论哪个分支 Git “看到”重命名:一个提示提交有重命名,另一个有删除,如与合并基础相比)。
找到合并基础提交。这里有一个并发症,但如果有并发症,它会立即出现。跑:
git merge-base --all srcbranch tgtbranch
例如,就我而言,我得到:
$ git merge-base --all A B
3a5c9ae0669e9969f8986810ea03c5283e0ac693
如果这仅打印出一个提交哈希,那么您很好。如果它打印出多个,您可能应该转而使用方法#1。
现在您知道有一个合并基础,您可以运行两个git diff --find-renames
命令。添加--name-status
限制输出量的选项。您可能还想添加--diff-filter=RD
以仅显示重命名或删除的文件。就我而言,我忽略了这些选项,因为我所做的只是重命名或删除:
$ git diff --find-renames --name-status A...B
D orig-filename
$ git diff --find-renames --name-status B...A
R064 orig-filename new-filename
这显示了重命名/删除的文件:原始名称是orig-filename
,新名称是new-filename
.
这种三点语法A...B
(或在您的情况下为tgtname...srcname
and srcname...tgtname
)具有 . 独有的特殊含义git diff
。在git diff
——但不是在其他 Git 命令1中——这意味着在两个指定的提交之间找到一个合并基础,并将其用作 diff 的左侧。使用右手提交说明符作为差异的右侧。 由于只有一个合并基础,这会将合并基础与右侧参数命名的提交进行比较。
1特殊的三点语法适用于所有常见的 Git 差异引擎,包括git diff-tree
面向用户的git diff
.
在许多版本的 Git 中实现这一点的方式存在一个错误,即如果有多个合并基础,则结果是不可预测的。因此,请确保只有一个合并基础。
边注
如果我们直接检查索引文件,在这种未合并的状态下,我们会找到一条REUC
带有原始文件名的记录:
$ od -c .git/index
0000000 D I R C \0 \0 \0 002 \0 \0 \0 002 ] 264 256 x
0000020 2 270 ) P ] 264 256 x 2 227 221 220 \0 \0 \0 ~
0000040 \0 320 ! a \0 \0 201 244 \0 \0 003 351 \0 \0 003 351
0000060 \0 \0 \0 W D f 366 262 S 374 K g 354 ' I 276
0000100 375 қ ** | 037 W > 6 \0 006 R E A D M E
0000120 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000140 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 201 244
0000160 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 222 9 2 257
0000200 \f [ m 334 C 301 026 306 H 315 y 7 Y 224 233 f
0000220 0 \f n e w - f i l e n a m e \0 \0
0000240 \0 \0 \0 \0 T R E E \0 \0 \0 006 \0 - 1
0000260 0 \n R E U C \0 \0 \0 - o r i g - f
0000300 i l e n a m e \0 1 0 0 6 4 4 \0 0
0000320 \0 0 \0 214 354 + 214 330 360 004 N O 355 \b 243 '
0000340 4 331 225 \n W [ 037 026 216 K } 367 ? 373 354 364
0000360 [ ^ 364 b 001 371 6 , 3 370 320
0000373
索引必须以幻数开头DIRC
,然后是我的两个文件的普通索引条目(我只有两个,如git ls-files --stage
输出所示)。但是它有一个TREE
记录,我们可以在 offset 附近看到它0000240
,然后是REUC
下一行的记录。此 REUC 记录是允许git checkout -m
重现合并冲突的“撤消”记录。而且,正如我们所见,撤消记录实际上存储了原始文件名。
Git 真的应该让我们访问这些信息,也许通过git ls-files
或更方便地通过git status
. 唉,事实并非如此。
推荐阅读
- spring - Spring 集成:带蛇壳的 Json 转换器
- javascript - 如何将对象从 Javascript (Adobe CEP) 传递给 Adobe ExtendScript?
- javascript - Javascript 日期评估格式
- kubernetes - 如何在 Kubernetes 中选择 API 网关?
- ios - unrecognized selector sent to instance ***
- processing - How can I track where my mouse goes and then if it goes beyond 400 pixels then print "you lose"?
- amazon-ec2 - Add crontab job EC2 instance Operation not permitted
- javascript - 使用Jquery按类搜索元素时获取空数组
- ruby-on-rails - Why is joins on a relation executing multiple queries in the console
- assembly - 有没有办法以编程方式获取当前系统上存在的所有 BIOS 中断列表?