gpt4 book ai didi

git 将两个文件 merge 为一个并保留历史记录

转载 作者:太空狗 更新时间:2023-10-29 14:42:59 24 4
gpt4 key购买 nike

假设您在 git 存储库中有两个文件,例如 A.txtB.txt

是否可以将这两个文件 merge 成第三个文件 A+B.txt,删除原来的 A.txtB.txt 并全部提交,所以历史仍然保留?

也就是说,如果我询问 git log --follow A+B.txt 我会知道内容源自 A.txtB .txt 文件?

我试图将文件分成两个不同的分支,然后将它们 merge 到一个新文件中(同时删除旧文件),但无济于事。

最佳答案

长答案是"is"!

完全归功于 Raymond Chen 的文章 Combining two files into one while preserving line history :

假设您有两个文件:fruitsveggies

git blame for both fruits and veggies

The naïve way of combining the files would be to do it in a single commit, but you'll lose line history on one of the files (or both)

You could tweak the git blame algorithms with options like -M and -C to get it to try harder, but in practice, you don’t often have control over those options (eg. the git blame may be performed on a server)

The trick is to use a merge with two forked branches

  • In one branch, we rename veggies to produce.
  • In the other branch, we rename fruits to produce.
git checkout -b rename-veggies
git mv veggies produce
git commit -m "rename veggies to produce"
git checkout -
git mv fruits produce
git commit -m "rename fruits to produce"

Then merge the first into the second

git merge -m "combine fruits and veggies" rename-veggies

This will generate a merge conflict - that's okay - now take the changes from each branch's Produce file and combine into one - here's a simple concatenation (but resolve the merge conflict however you please):

cat "produce~HEAD" "produce~rename-veggies" >produce
git add produce
git merge --continue

The resulting produce file was created by a merge, so git knows to look in both parents of the merge to learn what happened.

git blame for produce

And that’s where it sees that each parent contributed half of the file, and it also sees that the files in each branch were themselves created via renames of other files, so it can chase the history back into both of the original files.

Each line should be correctly attributed to the person who introduced it in the original file, whether it’s fruits or veggies. People investigating the produce file get a more accurate history of who last touched each line of the file.

For best results, your rename commit should be a pure rename. Resist the temptation to edit the file’s contents at the same time you rename it. A pure rename ensure that git’s rename detection will find the match. If you edit the file in the same commit as the rename, then whether the rename is detected as such will depend on git’s “similar files” heuristic.

checkout the full article获取完整的分步分解和更多解释


本来我以为这可能是a use case对于git merge-file做这样的事情:

>produce echo #empty
git merge-file fruits produce veggies --union -p > produce
git rm fruits veggies
git add produce
git commit -m "combine fruits and veggies"

然而,所有这一切都有助于模拟针对两个不同文件的 merge 差异算法 - 提交时的最终输出与手动更新文件并手动提交所产生的更改相同

关于git 将两个文件 merge 为一个并保留历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46611465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com