重写git历史记录以使crlf保持一致

时间:2013-05-22 07:59:18

标签: git dos

我有一个git存储库,它具有LF和CRLF文件的精细变体。

在进行可能的切换之前,我想重写提交,其中父级和当前提交具有​​不同的LR / CRLF编码。

所以我尝试了以下“one-liner”(稍加编辑),如果文件的父版本包含CR,我会尝试运行todos

$ git filter-branch --tree-filter '
  echo
  P=$GIT_COMMIT^;
  FILES=$(git diff --name-only $P);
  for a in $FILES; do
     if ! git cat-file -e $P:$a; then echo "no parent"; continue; fi;
     if git show $:$a | grep -qUP '\r'; then
        echo "parent is dos";
        todos $a;
     else
        echo "parent is unix";
        fromdos $a;
     fi;
  done' 23498f..HEAD

它不起作用。任何人都可以发现错误或解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

我正在回答我自己的问题。我的原始解决方案中的错误是FILES集合是错误的,因为在重写的父级和当前提交之间没有取得差异,而是在原始之间取得差异父和当前提交。

当遍历一组这样的提交时,需要更改的文件不是提交所触及的文件集,而是一些父提交搞乱了行结尾的文件集。

这意味着我没有获得正确的文件集。有一个map函数提供给filter-branch表达式,可以将“原始”rev转换为重写的rev。当我使用该功能时,它可以正常工作。

由此产生的“单线”看起来像这样:

$ git filter-branch -f --tree-filter '                         
    echo "\n $GIT_COMMIT";
    P=$(git rev-parse $GIT_COMMIT^);
    echo $P;
    P=$(map $P);
    echo $P;
    git cat-file commit $GIT_COMMIT;
    FILES=$(git diff --name-only $GIT_COMMIT $P);
    echo "FILES:\n$FILES"; 
    for a in $FILES; do
        git cat-file -e $P:$a > /dev/null 2>&1 || continue;
        if git show $P:$a | grep -qUP '\r'; then
           echo "parent is dos $a";
           todos $a;
        else
           echo "parent is unix $a";
           fromdos $a;
        fi;
    done;
    git add $FILES;' a6d9e..HEAD 

大多数aI不认为需要最后一个'git add $ FILES',但这是我使用的命令,我不想提供错误的答案。

注意:还应该可以定义FILES=$(git diff --name-only a6d9e HEAD),因此在遍历提交时使用固定集。这可能更简单,但我没有这样做。

答案 1 :(得分:1)

你真的想重写历史吗?

使用内置配置选项有助于使这些内容透明化。我已经做了类似的事情,并且在过去的几年里,与Windows,Mac和Linux系统上的人一起工作尚未遇到行结尾的问题。

从GitHub查看Dealing With Line Endings

以下是他们对配置文件的看法:

  

这是一个示例.gitattributes文件,您可以将其用作所有存储库的模板:

# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted 
# to native line endings on checkout.
*.c text
*.h text

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary The advantage of this is that your end of line configuration now travels with your repository and you don't need to worry about whether or not collaborators have the proper global settings.

如果你有一个当前的存储库,他们会继续讨论你可以做些什么,并且需要将这些设置应用到它。

重新规范存储库

  

设置core.autocrlf选项并提交后   .gitattributes文件,你可能会发现git想要提交那些文件   你没有修改过。这是因为git想要规范化线   为你结束。执行此操作的最佳方法是清除工作树   (除.git目录之外的所有文件)然后恢复它们。使   确定你在做这件事之前已经做过任何工作,否则就会丢失。

git rm --cached -r .
# Remove everything from the index.

git reset --hard
# Write both the index and working directory from git's database.

git add .
# Prepare to make a commit by staging all the files that will get normalized.
# This is your chance to inspect which files were never normalized. You should
# get lots of messages like: "warning: CRLF will be replaced by LF in file."

git commit -m "Normalize line endings"
# Commit