如何禁用 git cherry-pick 将一个文件的差异应用于另一个文件?

huangapple go评论70阅读模式
英文:

How can I disable git cherry-pick from applying the diff of one file to another?

问题

复现我的情况的步骤,

git 初始化 foo
进入 foo 目录

# 在 "master" 分支上添加初始 a.txt
echo hello > a.txt
git add a.txt
git 提交 -mbase

# 创建分支 "new"
git 分支 新

# 在 "master" 分支上将 a.txt 重命名为 b.txt
git mv a.txt b.txt
git 提交 -m'rename a.txt to b.txt'

# 在 "master" 分支上修改 b.txt
echo world >> b.txt
git 提交 -am'world b'

# 在 "new" 分支上将 a.txt 重命名为 c.txt
git 切换到 new
git mv a.txt c.txt
git 提交 -m'rename a.txt to c.txt'   # 锚点 1

# 应用修改了 b.txt 的提交
git cherry-pick master

在分支 new 上,b.txt 不存在,只有 c.txt,我预期 git cherry-pick 会因冲突而失败。然而,它成功了,并将 b.txt 的差异应用到了 c.txt

我猜这与 b.txtc.txt 被视为从同一源 a.txt 复制而来有关,可能也与某些 git 合并策略有关。我尝试解决这个问题,

# 删除 foo,再次运行命令,并在 # 锚点 1 处暂停

# 从 "master" 向 "new" 引入 b.txt
git checkout master -- b.txt
git 提交 -m'add b.txt from master'

# 应用修改了 b.txt 的提交
git cherry-pick master

这样,它会如预期地投诉 nothing to commit, working tree clean。但是,在我的项目中,这种情况非常普遍,我不能在工作流程中放弃 git cherry-pick。由于创建和重命名不在我的控制之下,我不能要求其他团队成员始终将所有新文件应用到根本不需要它们的其他分支。

有没有办法禁用 git cherry-pick,使其不将一个文件的差异应用到另一个文件上而没有任何不良副作用?谢谢。

我尝试了 Ubuntu 上的 git 2.19.2、2.24.1 和 2.39.0。

英文:

The steps to reproduce my case,

git init foo
cd foo

# add initial a.txt on "master"
echo hello > a.txt
git add a.txt
git commit -mbase

# create branch "new"
git branch new

# on "master", rename a.txt to b.txt
git mv a.txt b.txt
git commit -m'rename a.txt to b.txt'

# on "master", modify b.txt
echo world >> b.txt
git commit -am'world b'

# on "new" rename a.txt to c.txt
git switch new
git mv a.txt c.txt
git commit -m'rename a.txt to c.txt'   # Anchor 1

# apply the commit in which b.txt is modified
git cherry-pick master

As on branch new, b.txt does not exist and it has only c.txt, I expected git cherry-pick to fail due to conflicts. However, it succeeded and applied the diff of b.txt to c.txt.

I guess it's related to the fact that b.txt and c.txt are considered as being copied from the same origin a.txt, and maybe also some git merge strategy. I had a try to solve the issue,

# remove foo, run the commands again, and pause at # Anchor 1

# introduce b.txt from "master" to "new"
git checkout master -- b.txt
git commit -m'add b.txt from master'

# apply the commit in which b.txt is modified
git cherry-pick master

This way, it complains nothing to commit, working tree clean as expected. But, in one of my projects the situation is very common, and I cannot abandon git cherry-pick in the workflow. As the creation and renaming are not under my control, I cannot ask other team members to always apply all new files to other branches where they are not necessary at all.

Is there any solution to disable git cherry-pick from applying the diff of one file to another without any bad side effect? Thanks.

I tried git 2.19.2, 2.24.1 and 2.39.0 on Ubuntu.

答案1

得分: 1

‘resolve’合并策略…

[…]不处理重命名。

使用--strategy选择‘resolve’。

继续作为示例从锚点1开始:

$ git cherry-pick --strategy=resolve master
尝试简单合并。
简单合并失败,尝试自动合并。
错误:b.txt: 不处理情况… ->  -> …
致命错误:合并程序失败
错误:无法应用…... world b

$ git status
位于分支new
您正在进行提交…的cherry-pick。

未合并的路径:
	由我们删除:b.txt

未添加更改以进行提交
英文:

The ‘resolve’ merge strategy…

> […] does not handle renames.

https://git-scm.com/docs/git-merge#Documentation/git-merge.txt-resolve

Use --strategy to choose ‘resolve’.

https://git-scm.com/docs/git-cherry-pick#Documentation/git-cherry-pick.txt---strategyltstrategygt

Continuing from anchor 1 as an example:

$ git cherry-pick --strategy=resolve master
Trying simple merge.
Simple merge failed, trying Automatic merge.
ERROR: b.txt: Not handling case … ->  -> …
fatal: merge program failed
error: could not apply …... world b

$ git status
On branch new
You are currently cherry-picking commit ….

Unmerged paths:
	deleted by us:   b.txt

no changes added to commit

huangapple
  • 本文由 发表于 2023年4月13日 15:58:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003008.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定