git filter-branchs不覆盖远程分支

时间:2018-11-30 22:04:18

标签: git git-filter-branch

在本教程https://help.github.com/articles/removing-sensitive-data-from-a-repository/中,我正在尝试过滤分支。

git filter-branch --force --index-filter "git rm -r --cached --ignore-unmatch $1" --prune-empty --tag-name-filter cat -- --all
git push --force --all

仅过滤分支主节点,而不过滤orgin /分支。我不得不编写此脚本:

for branch in $(git for-each-ref --format='%(refname)' refs/)
do
    git checkout $branch
    git filter-branch --force --index-filter "git rm -r --cached --ignore-unmatch $1" --prune-empty --tag-name-filter cat -- --all
    git push --force --all
done

有什么想法可以让我获得第一个命令来遍历所有引用,这样我就不必自己进行遍历了吗?

1 个答案:

答案 0 :(得分:1)

  

[{git filter-branch ... --all]仅过滤分支主服务器,而不过滤orgin /分支...

这是正常且可取的,因为origin/名称实际上根本不是 branch 名称。 (Git称它们为远程跟踪分支名称,我认为这听起来太像“分支名称”了-毕竟这里有短语“分支名称”!它们的“远程跟踪名称”以帮助区分它们。)

远程跟踪的名称是您的 Git对某些 other Git分支的记忆。当您使用git filter-branch时,是在告诉Git复制存储库中的提交,在提交副本之前进行一些更改,然后更新您的分支名称以指向新复制的(可能是新的和改进的)提交,而不是原始的(旧的和糟糕的?)提​​交。

您随后的git push --force --all要求您的Git将所有您的分支名称和其相应的提交哈希ID以及您缺少的origin提交提交给他们的Git,所有这一切。然后,您的Git命令(--force)的Git以与您相同的方式设置分支名称,即指向复制的,经过改进的新提交。如果他们接受此命令,您的Git将更新您的远程跟踪名称。

通常,您要做的是找到与分支名称相对应的所有远程跟踪名称:

git for-each-ref refs/remotes/origin  # add --format options as appropriate

,并使用这些名称来确保您拥有自己的 分支名称,并指向与这些远程跟踪名称相同的提交。以下内容未经测试,因此请先进行验证。出现错误时,它实际上也不会失败(因为prog | while ...太难了),它只是打印警告。

git for-each-ref --format='%(refname)' refs/remotes/origin |
    while read name; do
        shortname=${name#refs/remotes/}
        localname=${name#refs/remotes/origin/}
        # if we have a branch named $localname, make sure it
        # identifies the same commit as $name.  If not, create
        # one pointing to $name.
        fullname=refs/heads/$localname  # use full name in case of tags etc
        if hash=$(git rev-parse $fullname); then
            if test $hash != $(git rev-parse $name); then
                echo "WARNING: local branch $localname differs from $shortname"
            else
                echo "local branch $localname is good (matches $shortname)"
            fi
        else
            echo "creating local branch $localname to match $shortname"
            # NB: you can add --track here but that is the default anyway
            if ! git branch $localname $name; then
                echo "WARNING: failed to create $localname"
            fi
        fi
    done

现在,每个远程跟踪分支实际上都有一个分支(加上您自己的任何没有远程跟踪名称的分支)。 现在 --all上的filter-branch可以满足您的需求。

还有另一个问题,也许是次要的或无关紧要的。您的过滤器分支说:

... --tag-name-filter cat ...

告诉您的git filter-branch更新您的任何标签。但是您最后的git push表示git push --force --all,而--all中的git push表示推送所有分支,而不是推送所有分支和标签。如果您的git filter-branch did 更新了一些标签,您可能也应该推送它们。

请注意,在公共存储库中更改标签通常不是一个好主意,因为要确保这些存储库的所有其他用户选择与现有标签名一起使用的新标签值是很棘手的。不过,如果合适的话,应该继续进行下去,并向所有 用户警告该公共存储库中的标签已更改。