在一系列提交中运行filter-branch

Aco*_*orn 46 git git-filter-branch

git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="foo@example.com"
export GIT_AUTHOR_NAME="foo"' -- commita..commitb
Run Code Online (Sandbox Code Playgroud)

结果是 Which ref do you want to rewrite?

因此,似乎filter-branch不允许您使用范围表示法使用两个任意引用之间的范围.

如果不可能采用这种方法,那么在一系列连续提交(分支历史中某处)上运行过滤器的最直接方法是什么.

Ped*_*ção 30

如@kan所说,你不能在历史中间应用过滤器分支.您必须从已知的提交申请到历史的末尾

git filter-branch --env-filter '...' SHA1..HEAD
Run Code Online (Sandbox Code Playgroud)

Filter-branch可以检查提交作者或其他信息,选择是否更改提交,因此有多种方法可以实现您想要的,请参阅http://git-scm.com/book/ch6-4.html,寻找"全球改变电子邮件地址"

请记住:如果您已将提交推送到公共存储库,则不应使用filter-branch

  • * PSA:*它不能重写历史记录的中间部分,因为它将使附加到中间部分的尾端的父字段无效。 (2认同)

Aco*_*orn 23

我找到的最干净的解决方案是执行以下操作:

  1. refb.创建一个临时分支.
  2. 应用分支过滤器refa..temp.
  3. 重新登录临时分支并删除它.

即.

git branch temp refb

git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="foo@example.com"' refa..temp

git rebase temp
git branch --delete temp
Run Code Online (Sandbox Code Playgroud)


qqx*_*qqx 11

git filter-branch 确实接受范围表示法,但范围的结尾需要是引用,而不是提交的ID.

git checkout -b tofilter commitb
git filter-branch .... commita..tofilter
Run Code Online (Sandbox Code Playgroud)

如果只是提交,它将不知道什么引用过滤分支更新.

  • 在这种情况下,如何阻止我的过滤器脚本在commita之前应用于提交并在commitb之后提交? (4认同)

Chr*_*ial 6

将过滤器命令包含在检查该范围的if语句中.您可以使用以下命令检查提交是否在给定范围内:

git rev-list start..end | grep **fullsha**
Run Code Online (Sandbox Code Playgroud)

当前提交将存储$GIT_COMMIT在您的过滤器中.所以你的过滤器变成:

git filter-branch --env-filter '
  if git rev-list commita..commitb | grep $GIT_COMMIT; then
    export GIT_AUTHOR_EMAIL="foo@example.com"
    export GIT_AUTHOR_NAME="foo"
  fi' -- ^commita --all
Run Code Online (Sandbox Code Playgroud)

如果您只想重写当前分支,请替换--allHEAD


kan*_*kan 5

您不能只覆盖历史中间的提交,因为提交的 sha1 取决于父项。所以,git 不知道过滤后你想把你的 HEAD 引用指向哪里。因此,您应该将所有内容重写为 HEAD。

例子:

A---B---C---D---E---F   master
            \
             \--G---H   branch
Run Code Online (Sandbox Code Playgroud)

如果您想过滤提交 B 和 C,您还应该过滤以下所有提交:D、E、F、G、H。所以,这就是为什么 git 告诉您在范围末尾使用 ref,这样它就不会完成一个分离的头。

修改 B 和 C 提交后,停止将如下所示:

A---B---C---D---E---F   master
\           \
 \           \--G---H   branch
  \-B'--C'      (HEAD or a temporary TAG?..)      
Run Code Online (Sandbox Code Playgroud)

因此,masterbranch将保持不变。我不认为这是你想要的。这意味着您必须覆盖所有提交。历史将是:

A---B---C---D---E---F   (loose end, will be garbage collected one day)
\           \
 \           \--G---H   (loose end, will be garbage collected one day)
  \-B'--C'--D'--E'--F'  master
            \
             \--G'--H'  branch
Run Code Online (Sandbox Code Playgroud)


Mar*_*rra 5

我这样做。

假设您要过滤名为 branch-you-are-filtering 的分支的内容。

假设有一个祖先提交到该分支,引用名为 ref-for-commit-to-stop-at。

git filter-branch --commit-filter 'YOUR_FILTER_COMMANDS' branch-you-are-filtering...ref-for-commit-to-stop-at
Run Code Online (Sandbox Code Playgroud)

执行后,ref-for-commit-to-stop-at 处的提交不会改变。分支 branch-you-are-filtering 中所有已过滤\更改的提交都将基于 ref-for-commit-to-stop-at。

您是否使用 --commit-filter 或其他东西取决于您。