代码之家  ›  专栏  ›  技术社区  ›  gavenkoa

修复了Git中如果contributor的autocrlf为true,则所有提交都被破坏的问题

git
  •  1
  • gavenkoa  · 技术社区  · 7 年前

    由于Git CR自动删除,即使只更改了一行,我也得到了提交全部中断的分支。

    我们的存储库本身已损坏:它是从SVN转换而来的,没有剥离CR。

    所以任何没有 autocrlf = input 修复CR/LF自动结束。

    我用monstrous系列修复了断开的提交,如 core.autocrlf=false 并在文件中添加/删除最后一行以使它们有所不同):

    git co broken
    git co -b fixed HASH_OF_BROKEN
    git -c core.autocrlf=false reset --hard
    
    for f in broken.txt; do echo >>$f; unix2dos $f; done
    
    git -c core.autocrlf=false add -u
    git -c core.autocrlf=false ci --amend --no-edit
    
    for f in broken.txt; do sed -i '$ d' $f; done
    
    git -c core.autocrlf=false add -u
    git -c core.autocrlf=false ci --amend --no-edit
    
    git cherry-pick HASH_OF_NEXT_TO_BROKEN..broken
    git push origin fixed
    

    是否有简单的方法修复以下结果:

    warning: CRLF will be replaced by LF in ...
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Schwern    7 年前

    如果目标是拥有一个具有一致行尾的存储库,那么最好使用 git-filter-branch 而不是一个接一个地处理它。假设您想要一致的DOS行结尾。

    编写一个小程序,可以转换目录树中所有文件的行尾,除了 .git 。如果你有二进制文件,你也必须跳过它们。这里有一个简单的例子。

    $ cat ~/bin/all2dos
    #!/bin/sh
    
    find . -path ./.git -prune -o -type f -print0 | xargs -0 unix2dos
    

    然后在 tree-filter 在所有历史记录中转换每次提交的行尾。

    $ git filter-branch --tree-filter 'all2dos' -- --all
    

    虽然改写历史很可怕,但在一段时间内是完全可逆的。Git不会重写提交,而是编写新的提交并使用它们。您的原始提交可以通过 reflog 你可以把你的树枝移回它们那里。

    $ git reflog
    10eed67 (HEAD -> master) HEAD@{0}: filter-branch: rewrite
    e8615e3 HEAD@{1}: commit (initial): Test files
    

    也就是说最初的承诺 master e8615e3 新重写的是 10eed67 .我可以移动 主人 使用返回原始 git reset --hard e8615e3

    git pull --rebase=preserve 更新(他们无论如何都应该这样做)可能使用 --ignore-cr-at-eol 避免因换行而发生冲突。如果他们有任何开放的分支,他们将在旧的 主人 ; 他们应该 git rebase master 以新重写的 主人 树枝