0

有人问我是否可以修改 git 历史记录中包含其他开发人员不适当措辞的项目的一组签入注释。

有人可以告诉我如何实现这一点(或确认这是否不可能)?我是 TFS 的管理员,所以访问权限不是问题。我们的 TFS 使用 SQL Express 和 GIT 作为源代码控制。TFS 版本为 15.117.26714.0

我们在本地机器上使用 Visual Studio 2017 和 Team Explorer 插件。

4

2 回答 2

4

可以做到,但可能会很麻烦。根据审计规则的性质,您可能会考虑 git notes 是否提供更好的解决方案。(如果您只是缺少信息,并且如果您的审核员会同意,那么添加注释可以让您在最小的干扰下放入附加信息。如果您需要删除信息 - 如果有人输入密码或组织上不可接受的语言, 或任何信息 - 那么这将无济于事。)

您可能会注意到,其他一些源代码控制系统允许您更自由地编辑提交消息。我不想在此基础上为我的团队做出源代码控制工具的决定,但如果这是您的团队经常需要的,这是一个考虑因素。或者,更好的办法是弄清楚是否需要调整任何东西,这样就不会成为未来的频繁要求。

(在某种程度上,这可能是关于提交消息中需要和/或禁止的内容的培训问题。您可能能够使用挂钩设置某种护栏 - 如果您的托管环境,预接收挂钩是最重要的将让您配置一个,并且预先提交钩子为开发人员提供了一个很好的便利,以确保任何错误“快速失败”。)

问题是提交消息是提交的一个组成部分。当您修改提交的消息(我们称之为P)时,您实际上是在创建一个新的提交 ( P')。此外,如果您有一个提交C并且您想将其父级从 更改PP',那么您必须将其替换为新的提交C'

修改提交与用新提交替换它们之间的区别听起来并不大,但实际上这意味着您正在从已发布分支的历史记录中删除原始提交,这就是问题所在。

要进行清理,请从任何克隆开始。假设我们有以下内容,其中命名为“x”的提交有错误的提交消息。

x -- x -- x -- A <--(master)(origin/master)
 \
  x -- x - x -- B -- x <--(branch1)(origin/branch1)
   \      /
    x -- C -- x <--(branch2)(origin/branch2)

修复A不是太难。

git checkout master
git commit --amend

将显示一个编辑器,您可以重写提交消息。(或者您可以包含git commit诸如-m指定提交消息之类的选项。)然后您就有了

            A' <--(master)
           /
x -- x -- x -- A <--(origin/master)
 \
  x -- x - x -- B -- x <--(branch1)(origin/branch1)
   \      /
    x -- C -- x <--(branch2)(origin/branch2)

请注意,它A仍然存在并且origin/master仍然指向它。这个很重要。这意味着当您要更新时,origin您必须说

git push -f

这将“破坏”其他所有人的克隆。有关问题和典型清理过程的更多信息,请参阅“从上游 Rebase 恢复”下的git rebase文档 ( https://git-scm.com/docs/git-rebase );但还要注意,如果结果证明这会重写大部分 repo,您​​可能希望遵循如下的转换过程:

  • 每个人都推送他们所有的代码;它不需要完全合并,但必须在origin,因为
  • 每个人都丢弃他们的克隆
  • 你做你的清理工作
  • 每个人都制造一个新的克隆

无论如何,你已经清理了一个提交。到B. 这次它不是分支提示,所以amend不是要使用的东西。而是做一个rebase.

git rebase -i branch1~2 branch1

您将获得一个“待办事项”列表,其中显示了在branch1. 找到 的条目B并将行的开头从 更改pickreword。然后让 rebase 继续,当它到达时,B它会给你一个提交消息的编辑器。最后你有

            A' <--(master)
           /
x -- x -- x -- A <--(origin/master)
 \
  x --- x --- x -- B -- x <--(origin/branch1)
   \         / \
    \       /   B' -- x' <--(branch1)
     \     /
      x - C -- x <--(branch2)(origin/branch2)

A不比;差太多。您由于重新设置而重写了x提交,但最终它仍然只是强制推送的另一个参考。

现在呢C?好吧,C可以从多个 ref 访问,并且对于其中一个提交,它们之间有一个合并。这些因素使得rebase正确使用变得更加困难。在这种情况下,您可能需要使用git filter-branch. (如果您有任何案例让您使用filter-branch,那么您可能会考虑只做一个filter-branch来完成所有重写,而不是搞乱个人rebaseamend操作。)

问题在于如何编写msg-filter. 您可以编写一个脚本来检查提交 ID,对于每个已知的“错误”提交输出相应的新提交消息,而对于其他所有内容,只需cat返回原始消息。或者你可以为每个提交启动一个编辑器,如果没有太多的提交不实用的话。或者介于两者之间(为每个 ID 在某个列表中的提交启动一个编辑器)。有太多的方法和太多的原因会影响使用哪种方法,无法在此答案中详细说明。

假设你整理了一个过滤器脚本,你会做类似的事情

git filter-branch --msg-filter=my-filter-script -- --all

The full diagram for this result gets messy, but basically for the local branches C is replaced with C', everything that can reach C is similarly replaced, and each branch from which C is reachable needs to be force pushed.

于 2018-01-26T16:56:45.973 回答
1

从命令行,您可以使用

git rebase -i <sha-hash of the first commit to edit>~

(注意末尾的波浪号。您必须按字面意思输入。)

键入此内容后,将打开一个文本编辑器,其中包含所有提交的列表以及如何处理它们的命令。该命令默认为pick. 对于您要编辑的内容,请选择reword。然后保存文件并关闭文本编辑器。现在,对于您选择改写的每个提交,编辑器将再次打开并允许您编辑提交消息。编辑后,只需保存并关闭即可。

请注意,这将从您开始时重写整个 git 历史记录。之前已将此历史记录提取到本地存储库的任何人都需要git fetch然后git reset --hard <branch name>. 如果他们没有这样做,那么有问题的提交将在他们继续工作时保留在 repo 中。

于 2018-01-26T15:04:29.127 回答