Git 使用重命名的文件进行变基
Git rebase with renamed files
我有一个重命名许多文件的分支,我正在尝试将其重新定位到 master
原始文件已被修改的地方(最好不要将其演变成手动解决冲突的噩梦) .
情况
我一直在将 JavaScript 项目移植到我本地 typescript
分支中的 TypeScript。所有 .js
文件现在都变成了 .ts
文件,并且一些语法已经升级。
同时,master
分支上发生了对原始 .js
文件的更改。
我想 rebase 我的 typescript
分支到 master
-- 但更改没有正确合并,因为文件未检测到重命名——因此我们在对 .js
文件进行更改时发生冲突,git 认为这些文件已被删除(但它们实际上已重命名为 .ts
文件).
我认为我知道的
Git 图:
o-[typescript] .js files become .ts
|
| o-[master] changes to the .js files
| |
| o
|/
o-[root] common ancestor
因此,当站在 root
分支时:
我可以运行这个命令来查看所有的重命名:git diff --name-status --find-renames=10% typescript
我知道 git merge 命令具有相同类型的 --find-renames
功能,但我很难让它发挥作用。
- 更新:
git merge -X find-renames=10% mybranch
似乎是预期的语法。
我了解 git rebase 可能 支持 find-renames
功能,但我仍然不清楚如何使用它.
解决思路?
(不) 也许从 root
开始,我可以在检测重命名时合并到 typescript
(像这样:git merge -X find-renames=10% typescript
).然后,root 将与 typescript
一样,除了重命名(而不是质量 deletions/additions)。
- 从那里开始,我希望我可以
git rebase master
,并且在重命名到位后,操作将顺利进行并将编辑内容放入正确的文件中。
- 更新:我试过了,但我后来的变基并没有比以前好多少。
(是的) 我想也许 rebase 本身需要使用 find-renames
选项来执行。我正在调查这个。 .
git rebase -X find-renames=10% master
-- 没有
git rebase -X --find-renames=10% master
-- 没有
git rebase --find-renames=10% master
-- 没有
git rebase -X recursive --find-renames=10% master
-- 没有
git rebase --merge -X find-renames=10% master
-- 没有
git rebase --strategy-option="rename-threshold=10" master
-- 这就是门票!有效!
(不) 也许我需要换个角度看问题?也许我应该从 master
开始,然后通过重命名检测对 typescript
进行某种压缩合并(而不是任何类型的变基?)
- 我不需要
typescript
分支历史,无论如何它都会被压缩成一个 fat commit 以供审查..
- 更新: 当我尝试这个策略时,看起来 Git 停止工作了。当我站在
root
分支时,我可以运行 git merge -X find-renames=10 typescript
——它快进到 typescript
..(不是我所希望的,我希望有一个重命名的新提交而不是 [=169= ..)
- 当我站在
master
分支时,我 运行 完全相同的命令 , git 告诉我这个:fatal: Unknown option for merge-recursive: -Xfind-renames=10
...
- 现在,这让我很困扰,因为我实际上没有输入它引用的内容(我确实包括了 space),唯一对我来说不同的是我现在站在哪个分支在 -- 如果选项是 "Unknown",那么为什么它在不同的分支中 有效 ?
- 无论如何,这很令人毛骨悚然,而且似乎让这种方法走上了死胡同。
首先在 master
分支重做文件重命名可能会有所帮助。这似乎是一项相当机械的任务,如果需要可以自动化。
那么在此基础上对 typescript
分支进行变基可能会相当容易,因为已经有了共同点。变基 typescript
的一些提交最终(几乎)是空的,因为它们的更改已经包含在 master
.
中
出于这个原因,您可能需要考虑将 typescript
合并到 master
中,以保持原始的 .js
→ .ts
转换历史完整无缺。
您可以像这样在检测重命名时变基您的分支:
git rebase --strategy-option="rename-threshold=10" master
编辑: 从 Git 2.8.0 开始,术语 'rename-threshold' 已被弃用,取而代之的是 'find-renames' .
目前我使用的是 Git 2.7.4,因此我只能实际验证上述命令是否适用于我的情况——您可能需要使用术语 'find-renames' 如果上述命令在您的新版本 Git...
上对您的情况不起作用
在这个例子中,
- 当前分支重新基于
master
- 指定了
10%
的重命名阈值
master
中对原始文件的更改将放在新的(重命名的)文件中 (与 运行 仅 git rebase master
相对)。
- 请注意语法与
git diff
、git log
和 git merge
命令中的类似重命名检测功能相比有何不同
git rebase 文档对于这个重命名检测方面不是很清楚。我想我在某个地方读到另一个命令,术语 "rename-threshold" 已被弃用,虽然在这个context find-renames
似乎不能用作同义词 - 所以如果有人知道 运行 这个相同命令的更好方法,请提及 :)
除了 find-rename
rebase/merge strategy 之外,在 Git 2.29(2020 年第 4 季度)中,用于解释定序器机制放置的冲突块每一面的提交标签已变得更易于人类阅读.
参见 commit 7d056de (12 Aug 2020) by Elijah Newren (newren
)。
(由 Junio C Hamano -- gitster
-- in commit 6cceea1 合并,2020 年 8 月 19 日)
sequencer
: avoid garbled merge machinery messages due to commit labels
Signed-off-by: Elijah Newren
Reviewed-by: Taylor Blau
Acked-by: Johannes Schindelin
sequencer's get_message()
exists to provide good labels on conflict hunks;
see commits
- d68565402a ("revert: clarify label on conflict hunks", 2010-03-20, Git v1.7.1-rc0)
- bf975d379d ("cherry-pick, revert: add a label for ancestor", 2010-03-20, Git v1.7.1-rc0)
- 043a4492b3 ("sequencer: factor code out of revert builtin", 2012-01-11, Git v1.7.1-rc0).
for background on this function.
These labels are of the form
...
or
parent of ...
These labels are then passed as branch names to the merge machinery.
However, these labels, as formatted, often also serve to confuse.
For example, if we have a rename involved in a content merge, then it results in text such as the following:
<<<<<<<< HEAD:foo.c
int j;
========
int counter;
>>>>>>>> b01dface... Removed unnecessary stuff:bar.c
Or in various conflict messages, it can make it very difficult to read:
CONFLICT (rename/delete): foo.c deleted in b01dface... Removed
unnecessary stuff and renamed in HEAD. Version HEAD of foo.c left
in tree.
CONFLICT (file location): dir1/foo.c added in b01dface... Removed
unnecessary stuff inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.
Make a minor change to remove the ellipses and add parentheses around the commit summary; this makes all three examples much easier to read:
<<<<<<<< HEAD:foo.c
int j;
========
int counter;
>>>>>>>> b01dface (Removed unnecessary stuff):bar.c
CONFLICT (rename/delete): foo.c deleted in b01dface (Removed
unnecessary stuff) and renamed in HEAD. Version HEAD of foo.c left
in tree.
CONFLICT (file location): dir1/foo.c added in b01dface (Removed
unnecessary stuff) inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.
我有一个重命名许多文件的分支,我正在尝试将其重新定位到 master
原始文件已被修改的地方(最好不要将其演变成手动解决冲突的噩梦) .
情况
我一直在将 JavaScript 项目移植到我本地
typescript
分支中的 TypeScript。所有.js
文件现在都变成了.ts
文件,并且一些语法已经升级。同时,
master
分支上发生了对原始.js
文件的更改。我想 rebase 我的
typescript
分支到master
-- 但更改没有正确合并,因为文件未检测到重命名——因此我们在对.js
文件进行更改时发生冲突,git 认为这些文件已被删除(但它们实际上已重命名为.ts
文件).
我认为我知道的
Git 图:
o-[typescript] .js files become .ts
|
| o-[master] changes to the .js files
| |
| o
|/
o-[root] common ancestor
因此,当站在 root
分支时:
我可以运行这个命令来查看所有的重命名:
git diff --name-status --find-renames=10% typescript
我知道 git merge 命令具有相同类型的
--find-renames
功能,但我很难让它发挥作用。- 更新:
git merge -X find-renames=10% mybranch
似乎是预期的语法。
- 更新:
我了解 git rebase 可能 支持
find-renames
功能,但我仍然不清楚如何使用它.
解决思路?
(不) 也许从
root
开始,我可以在检测重命名时合并到typescript
(像这样:git merge -X find-renames=10% typescript
).然后,root 将与typescript
一样,除了重命名(而不是质量 deletions/additions)。- 从那里开始,我希望我可以
git rebase master
,并且在重命名到位后,操作将顺利进行并将编辑内容放入正确的文件中。- 更新:我试过了,但我后来的变基并没有比以前好多少。
- 从那里开始,我希望我可以
(是的) 我想也许 rebase 本身需要使用
find-renames
选项来执行。我正在调查这个。 .git rebase -X find-renames=10% master
-- 没有git rebase -X --find-renames=10% master
-- 没有git rebase --find-renames=10% master
-- 没有git rebase -X recursive --find-renames=10% master
-- 没有git rebase --merge -X find-renames=10% master
-- 没有git rebase --strategy-option="rename-threshold=10" master
-- 这就是门票!有效!
(不) 也许我需要换个角度看问题?也许我应该从
master
开始,然后通过重命名检测对typescript
进行某种压缩合并(而不是任何类型的变基?)- 我不需要
typescript
分支历史,无论如何它都会被压缩成一个 fat commit 以供审查.. - 更新: 当我尝试这个策略时,看起来 Git 停止工作了。当我站在
root
分支时,我可以运行git merge -X find-renames=10 typescript
——它快进到typescript
..(不是我所希望的,我希望有一个重命名的新提交而不是 [=169= ..)- 当我站在
master
分支时,我 运行 完全相同的命令 , git 告诉我这个:fatal: Unknown option for merge-recursive: -Xfind-renames=10
... - 现在,这让我很困扰,因为我实际上没有输入它引用的内容(我确实包括了 space),唯一对我来说不同的是我现在站在哪个分支在 -- 如果选项是 "Unknown",那么为什么它在不同的分支中 有效 ?
- 无论如何,这很令人毛骨悚然,而且似乎让这种方法走上了死胡同。
- 当我站在
- 我不需要
首先在 master
分支重做文件重命名可能会有所帮助。这似乎是一项相当机械的任务,如果需要可以自动化。
那么在此基础上对 typescript
分支进行变基可能会相当容易,因为已经有了共同点。变基 typescript
的一些提交最终(几乎)是空的,因为它们的更改已经包含在 master
.
出于这个原因,您可能需要考虑将 typescript
合并到 master
中,以保持原始的 .js
→ .ts
转换历史完整无缺。
您可以像这样在检测重命名时变基您的分支:
git rebase --strategy-option="rename-threshold=10" master
编辑: 从 Git 2.8.0 开始,术语 'rename-threshold' 已被弃用,取而代之的是 'find-renames' .
目前我使用的是 Git 2.7.4,因此我只能实际验证上述命令是否适用于我的情况——您可能需要使用术语 'find-renames' 如果上述命令在您的新版本 Git...
上对您的情况不起作用在这个例子中,
- 当前分支重新基于
master
- 指定了
10%
的重命名阈值 master
中对原始文件的更改将放在新的(重命名的)文件中 (与 运行 仅git rebase master
相对)。- 请注意语法与
git diff
、git log
和git merge
命令中的类似重命名检测功能相比有何不同
git rebase 文档对于这个重命名检测方面不是很清楚。我想我在某个地方读到另一个命令,术语 "rename-threshold" 已被弃用,虽然在这个context find-renames
似乎不能用作同义词 - 所以如果有人知道 运行 这个相同命令的更好方法,请提及 :)
除了 find-rename
rebase/merge strategy 之外,在 Git 2.29(2020 年第 4 季度)中,用于解释定序器机制放置的冲突块每一面的提交标签已变得更易于人类阅读.
参见 commit 7d056de (12 Aug 2020) by Elijah Newren (newren
)。
(由 Junio C Hamano -- gitster
-- in commit 6cceea1 合并,2020 年 8 月 19 日)
sequencer
: avoid garbled merge machinery messages due to commit labelsSigned-off-by: Elijah Newren
Reviewed-by: Taylor Blau
Acked-by: Johannes Schindelin
sequencer's
get_message()
exists to provide good labels on conflict hunks;
see commits
- d68565402a ("revert: clarify label on conflict hunks", 2010-03-20, Git v1.7.1-rc0)
- bf975d379d ("cherry-pick, revert: add a label for ancestor", 2010-03-20, Git v1.7.1-rc0)
- 043a4492b3 ("sequencer: factor code out of revert builtin", 2012-01-11, Git v1.7.1-rc0).
for background on this function.These labels are of the form ... or parent of ...
These labels are then passed as branch names to the merge machinery.
However, these labels, as formatted, often also serve to confuse.
For example, if we have a rename involved in a content merge, then it results in text such as the following:
<<<<<<<< HEAD:foo.c int j; ======== int counter; >>>>>>>> b01dface... Removed unnecessary stuff:bar.c
Or in various conflict messages, it can make it very difficult to read:
CONFLICT (rename/delete): foo.c deleted in b01dface... Removed unnecessary stuff and renamed in HEAD. Version HEAD of foo.c left in tree. CONFLICT (file location): dir1/foo.c added in b01dface... Removed unnecessary stuff inside a directory that was renamed in HEAD, suggesting it should perhaps be moved to dir2/foo.c.
Make a minor change to remove the ellipses and add parentheses around the commit summary; this makes all three examples much easier to read:
<<<<<<<< HEAD:foo.c int j; ======== int counter; >>>>>>>> b01dface (Removed unnecessary stuff):bar.c CONFLICT (rename/delete): foo.c deleted in b01dface (Removed unnecessary stuff) and renamed in HEAD. Version HEAD of foo.c left in tree. CONFLICT (file location): dir1/foo.c added in b01dface (Removed unnecessary stuff) inside a directory that was renamed in HEAD, suggesting it should perhaps be moved to dir2/foo.c.