【问题标题】:What happened to the changes that I made using git filter-branch?我使用 git filter-branch 所做的更改发生了什么?
【发布时间】:2020-05-31 00:11:32
【问题描述】:

我第一次尝试使用git filter-branch 重写我的 git 历史记录。我通过编写一个(Python)脚本(我们称之为edit_file)来编辑文件(我们称之为target_file)来做到这一点。然后,我运行了这个命令:

git filter-branch --tree-filter "path/to/edit_file" HEAD

我得到了一个不错的输出流,这似乎表明我得到了我想要的效果,但是当查看target_file 时,我没有看到任何变化。当我直接运行edit_file 时,我的工作副本中的target_file 成功接收到我想要的编辑。

听起来我的改变存在于 git 扭曲的头脑中的某个深沉、黑暗和潮湿的隐蔽处,我只需要一个神奇的咒语来召唤我的改变。我不知道这是否正确,也不知道从哪里开始寻找,因为我读过的所有材料(包括官方 git 书)都表明,一旦 git filter-branch 完成,我正在处理的分支应该拥有edit_file 将在target_file 的每个版本上执行的更改...

停下来?

对不起,如果这有点啰嗦,但我不知道需要哪些细节(因为这是混淆的核心特征)。


更多细节:

我说它看起来像 filter-branch 的原因是:

  1. 我可以看到每次提交时都运行 edit_file 的输出,这表明所有提交都成功了。 edit_file 的输出会随着它在 target_file 的不同版本上运行而发生变化,并且我能够看到 edit_file 的不同输出,因为 git filter-branch 在历史中移动。

  2. 最后,我看到了这个:

    Ref 'refs/heads/my-branch' was rewritten
    

PS:在做 git filter-branch 之前,我跑了

git checkout -b my-branch

创建一个名为 my-branch 的新分支(并检查一下),以防 git filter-branch 出现严重错误。


在看到git filter-branch ... 没有改变target_file 之后,我跑了git checkout -b my-branch,但我想那什么也没做。我认为它可能会有所作为,因为git filter-branch 的最后一行似乎是说分支my-branch 已更改,但老实说我不明白那行的意思。

【问题讨论】:

  • git show 会告诉你这个文件现在在任何给定的提交中的样子。
  • @matt git show my_file 产生零输出。我假设通过添加更多标志,可以实现您提到的行为,但对我来说,这些行为是什么并不明显。你能发布一个完整的工作命令吗?
  • 好吧,我说的是“在任何给定的提交中”。你没有提交。你选择查看什么提交?
  • 我期望做的是向我展示每个提交,因为这将让我看到“这个文件现在在任何提交中的样子”。所以,你的问题的答案基本上是“是”。
  • 是的,但我说的是任何 given 提交。也许我们在这里说的不是同一种语言。我要告诉你的是:如果你想知道文件在特定提交中的状态,git show 有权告诉你。因此,如果问题是:我是否根据需要转换了我的文件? git show 将回答这个问题。您可以命名一个提交范围,但同样,为了告诉您实际的命令,我需要知道您在该范围端点处提交的名称。

标签: git git-filter-branch


【解决方案1】:

听起来我的变化存在于 git 扭曲的头脑中的某个深沉、黑暗和潮湿的隐蔽处,我只需要一个神奇的咒语来召唤我的变化。

这就是为什么你不再使用git filter-branch (it is obsolete, along with BFG)

你使用git filter-repo

【讨论】:

  • 好的。下次我会尽量记住这一点,但我已经使用了 filter-branch,所以我的 repo 处于某种我无法理解的奇怪状态。告诉我我应该做一些不同的事情并不能真正帮助我(除非有人可以让我借用他们的时间机器)。在尝试其他重写历史的方法之前,我需要撤消什么操作吗?
  • @allyourcode 您可以重置为保存在 refs/original 中的内容,然后重试:stackoverflow.com/a/27975288/6309
  • 啊。我现在明白为什么我之前没有尝试 filter-repo:我的 git 版本太低,而 sudo apt-get install git --upgrade 什么也没做,因为我的平台上已经有了最新版本。此外,必须安装随机的第三方软件有点烦人。反问:如果 filter-repo 这么棒,为什么 git 不自带呢?
  • 是的,尝试获取 filter-branch 会导致:xkcd.com/349。第三方解决方案 = 你会过得很糟糕。
  • @matt 是的,正如我在问题中提到的那样,我采取了预防措施。似乎它们就足够了,但我不知道该怎么说,因为 git 有时会混淆 AF。此外,看起来 filter-branch 已经内置了安全机制。
【解决方案2】:

所以...看起来 git filter-branch 除了在 .git 目录中留下奇怪的备份便便之外没有做任何事情。 git gc 不会出于任何原因清理它(也许应该有一个 git clean-poop 命令以及 gc?)。不知道会发生什么,除了

cd ..  # Assuming you are at the root of your repo
git clone --no-local original fresh-copy
cd fresh-copy

是的,即使我们正在制作本地副本,也需要 --no-local,因为 This. Is. GIIIIIIIIIT! 这可能是您在尝试 filter-branch 或 filter-repo 之前应该做的事情。不知道为什么文档不建议这样做,但无论如何。不要做我做的事,只需创建一个新分支就可以了。将 git filter-X 视为核武器。您不仅需要掩体来保护您;你需要一次性平行宇宙。

咬牙切齿后,我终于得到了 VonC 的建议,即使用 git-filter-repo 工作。如果像我一样,你的平台没有足够新的 git 版本来使用 git-filter-repo(需要 >= 2.22),你可以做类似的事情

sudo add-apt-repository ppa:git-core/ppa
# followed by the usual
sudo apt-get update
# song and dance routine...
sudo apt-get install git --upgrade

按照git *nix download page 的建议升级到“最新最好的”。这对我不起作用(所以要小心盲目地复制和粘贴上述建议),但显然,我的系统非常混乱,所以你的运气可能比我好。总之……

一旦你获得了足够新的 git 版本,你唯一需要的就是 git-filter-repo 脚本本身(令人惊讶的是,它只包含一个主文件)。因此,只需下载该straight from github,并将其粘贴在您的 PATH 中的任何位置。记得先 chmod +x 把它搞砸。

您很可能不想使用 --path 标志,因为它不仅仅针对您要编辑的一个文件。相反, --path 将删除所有其他文件。

考虑到这一点,您需要做的就是这样:

git-filter-repo --blob-callback 'import sys
sys.path.append("dir/where/your/edit_file/py/file/lives")
import my_module

new = my_module.modify(blob.data.decode())
new_bytes = new.encode()
assert isinstance(new_bytes, bytes), ""
blob.data = new_bytes
'

是的,这就是一个命令。 blob.data 包含 git-filter-repo 正在检查的任何文件的内容。此外,请注意它是一个字节对象,而不是 str。让我再次强调一个非常重要的点:这个操作会遍历每个文件(在每次提交中)。因此,如果您只打算修改一个文件,您的 my_module.modify 函数最好是非常有选择性的。 (git-filter-repo 真正需要的是一种让您的脚本检测 blob 路径的方法,而不仅仅是为您提供文件的内容。但希望您可以通过其内容来识别您的文件,而不仅仅是它的路径。)如果你搞砸了,这没什么大不了的,因为你可以直接删除新复制的目录并重新开始。

在这场磨难之后不要挖出你的眼睛。你的眼睛太宝贵了,不能被像 git 这样愚蠢的东西毁掉。随意在淋浴时大哭一场。嘿,至少你终于搞定了,you weren't eaten by sharks

哦,还有一件事:您在第一步中所做的 git clone 不会复制任何子模块,因为这很有意义并且太容易了。因此,您还必须在新副本中执行此操作(即使 git clone 确实复制了 .gitmodules 文件):

git submodule init
git submodule update

PS:您可能会从 Internet 上可用的各种 git 手册页生成器之一获得一些治疗价值。它们确实读起来像 git 手册页,尽管它们实际上是随机的乱码。

【讨论】:

  • 感谢您的反馈。不知道为什么它被否决了。 (除了帖子的“咆哮”语气,传统上是不受欢迎的:我理解你的沮丧)
  • 谢谢。如果人们认为 git 是他们最好的朋友,并且因为我对它无法使用而感到沮丧而生气,那么让他们对我在技术上准确但略有变形的答案投反对票。
  • 我很高兴你最终成功了:这将帮助其他人!
猜你喜欢
  • 2013-03-29
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2020-02-20
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多