【问题标题】:git cherry-pick range of commits aborts on files with whitespace differencegit cherry-pick 提交范围在具有空格差异的文件上中止
【发布时间】:2017-05-31 02:44:06
【问题描述】:

我正在清理从另一个开发团队接管的 git 存储库。新的开发团队不需要原始的 commit 哈希(众所周知,在交互式 rebase 中修改提交后,每个后续提交都有不同的哈希。),所以我可以rebase/cherry-pick/graft/filter-branch... 直到存储库“干净”为止。

另一个团队混合使用了 Windows 和 Linux 行尾。在master 上时,我添加了一个新分支,检查了cleanup 分支中的根提交,添加了一个合理的.gitattributes 文件,并修改了根提交。现在我的存储库有 2 个根提交,正如预期的那样。

接下来,我想将 master 分支挑选到 cleanup 分支(稍后将成为新的 master 分支)的根提交上。我使用了这个命令(14c4a129 显然是master 分支的根提交):

git cherry-pick 14c4a129..master -Xignore-space-change

但是,通过樱桃采摘的四分之一中止

error: Your local changes to the following files would be overwritten by merge:
        (list of files)
Please commit your changes or stash them before you merge.
Aborting

这些文件中的更改只是空白,因为git diff -w 变成空白。另一个线索:find src -type f -print0 | xargs -0 file | sort | grep 'CRLF' 给了我与git status 完全相同的文件列表。

当 git 日志中出现使用不同行尾的新开发人员时,就会发生这种情况。准确地说,在他的第二次提交时,樱桃采摘失败了。我假设发生的是,他的第一次提交得到了规范化的行结尾,但随后他的下一次提交再次获得了原始的 CRLF 行结尾,这与提交的文件冲突,在下一次提交可以被挑选之前.

但是,我期待 -Xignore-space-change 会为我解决这个问题,所以我根本不需要进行任何手动干预。看来我理解错了。

我也试过--strategy=recursive --strategy-option=renormalize,结果一样。

我还尝试使用master 分支的交互式变基,编辑(修改)根提交以添加.gitattributes,并保留所有后续提交 - 这与樱桃采摘基本相同,除了它发生在另一个分支。

使用假设的“overwrite-whatever-is-here-dammit”选项解决此问题的正确方法是什么?我也愿意接受涉及 master 分支的交互式变基的答案,我只修改根提交,因为最终结果与樱桃选择相同。

  • 在修改根提交后不需要任何人工干预的答案将被投票。
  • 导致手动修复单个提交的答案将被否决。
  • 那些让我进一步澄清我的问题的评论将被点赞。

【问题讨论】:

  • 我真的不在乎你是否对我投反对票,但我认为问一下为什么这很重要很重要:“新的开发团队不需要拥有原始的 SHA 哈希值”。即使按照您的建议(摘樱桃),也会有大量具有相同哈希值的对象。
  • 对象,是的。承诺,不。一旦你修改了一个提交,每个后续的提交都会有一个不同的哈希值。感谢您的提问,我会更新我的问题以澄清。

标签: git


【解决方案1】:

不要认为你可以使用交互模式:

--忽略空格 --whitespace= 这些标志被传递给应用补丁的 git apply 程序(参见 git-apply[1])。不兼容 --interactive 选项。

我尝试了一个简单的示例,所以我不确定这是否适合您。创建您的清理分支(只需 1 或 2 次提交)。切换到您的主分支。

git rebase cleanup --ignore-whitespace

解决过程中出现的任何合并问题

【讨论】:

  • 不幸的是,这也导致error: Your local changes to the following files would be overwritten by merge,在完全相同的提交上。如果我解决了这个问题,那么之后的每一次提交也需要人工干预。所以这与我之前尝试的结果相同。
  • 祝你好运,顺便说一句,我想知道你是否会使用“--whitespace=fix”选项来代替“--ignore-whitespace”。
  • 我现在正在尝试一种完全不同的方法:git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix'。仍然需要一些微调,因为我不希望 dos2unix 接触 png 文件之类的二进制文件。
  • --strategy-option=ours 看起来也很有趣。
【解决方案2】:

this Super User questionthis Stack Exchange question 的启发,我采取了完全不同的方法。我没有使用rebase/cherry-pick,而是直接使用git filter-branch 处理git 对象。

第 1 步:使用 dos2unix 过滤所有提交

我使用了这个命令:

time git filter-branch -f --tree-filter 'git ls-files -z | xargs -0 file | grep -e ":.*text" | grep "CRLF" | cut -d":" -f1 | tr "\n" "\0" | xargs -0 dos2unix' --prune-empty -- master

git filter-branch 遍历给定分支中的所有提交,并对每个提交应用过滤器。过滤器可以是 shell 命令甚至是外部 shell 脚本。事实上,如果您想要做的不仅仅是一次性的,我强烈建议您使用我的单线,而是将树形过滤器移到它的自己的脚本,或脚本中的函数。

解释tree-filter

  • git ls-files:输出当前在tree-filter 中的所有提交的文件名
  • -z:空行终止。我不得不使用它,因为有些文件带有空格和 特殊 字符。
  • xargs:从标准输入构建和执行命令行(从git ls-files的标准输出管道)
  • -0: 输入以空字符终止
  • file: 确定文件类型
  • grep -e ":.*text":在第二列中打印所有包含字符串“text”的行,这意味着所有文件都是某种文本文件(.html、.css、.js、.java,...)。实际上,由于下一个 grep 不需要此 grep,但我将其保留在那里作为额外的健全性检查。
  • grep CRLF:我只想处理以 CRLF (Windows) 行结尾的文本文件。没有这个,结果会是一样的,但是会慢很多,因为dos2unix 必须处理已经有 Unix 行结尾的文件。
  • cut -d":" -f1:使用第一个 f 字段,d 限定在 : 字符(来自 file 输出;幸运的是我没有文件名中包含: 字符的文件)
  • tr "\n" "\0":用 null 替换换行符,因为我们可能还有文件名中带有空格
  • dos2unix:DOS/Windows转Unix文本文件格式转换器

此命令需要一段时间才能完成:

662,44s user 18,82s system 96% cpu 11:47,10 total

第 2 步:将 master 分支变基到 cleanup 分支上

如问题中所述,已经有一个 cleanup 分支,有 1 个提交,其中包含一个 .gitattributes 文件。清理后的master 分支现在可以重新基于它。 --ignore-whitespace 不再需要,因为所有空白问题都已在步骤 1 中解决。这样做就足够了:

git rebase cleanup

没有发生合并错误。

第 3 步:打扫卫生

清理你不再需要的垃圾(我们毕竟做了备份,不是吗?嗯……是吗?)

git branch -D cleanup
git filter-branch -f --env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" && export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" && export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"' -- master
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git gc --aggressive --prune=now

第 4 步:推送到远程

git remote add origin $REPOSITORY
git push -u origin master

【讨论】:

    猜你喜欢
    • 2017-07-23
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 2021-01-18
    • 2018-04-17
    • 2012-05-21
    • 2016-10-24
    相关资源
    最近更新 更多