【问题标题】:Search git for a specific version of a file在 git 中搜索文件的特定版本
【发布时间】:2020-01-08 03:20:52
【问题描述】:

我有一个文件是在某个时候从 git 存储库复制的。我想找到文件被复制到的 SHA。

目前我将获取所有 SHA 的列表,并将每个 SHA 的文件与我拥有的文件进行比较,但我希望有更好的方法。

【问题讨论】:

  • 具有一个特定名称的文件可以在许多甚至每个提交中。每个提交都有一个文件副本。每个提交可能共享文件的相同副本,或者部分或全部提交可能具有该文件的不同副本。你到底想从 Git 中得到什么?有一种相对快速的方法可以找到该文件存在的每个提交并且与您拥有的副本完全匹配,但当然不能保证任何此类提交存在。
  • 理论上,您可以计算文件的 SHA,它应该对应于 Git repo 中某些 BLOB 的 SHA。使用 blob SHA,您可以通过 stackoverflow.com/questions/223678/which-commit-has-this-blob 找出哪些提交包含此 blob。这应该可以帮助您识别包含此类文件的第一个或最后一个提交。但是,如果您想找出从中复制文件的特定提交,那几乎是不可能的。
  • 要获取某个文件插入到 Git 存储库时的哈希值,请使用git hash-object
  • @torek 我认为 OP 可能会喜欢你提到的这种“相对快速的方式”(我有兴趣看到它)
  • @D.BenKnoble:啊哈,我没有看到--find-object 选项。它最初是在 Git 2.17 中引入的。它的作用类似于-S,因此它不会找到包含对象的每个提交,而是会找到添加或删除对象副本的每个提交。

标签: git


【解决方案1】:

在我看来,情况如下:

比方说,我们正在谈论文件foo.txt,它在某个时候被添加到了 git 存储库(比如说,空的):

touch foo.txt
git add foo.txt
git commit -m "added foo.txt"
// commit '123'

后来改了几次:

// add "hello" to foo.txt
git add foo.txt
git commit -m "Added 'hello'"
// commit '456'
// add "world" to foo.txt
git add foo.txt
git commit -m "Added 'world'"
// commit '789'

此时文件(包含“hello world”)被复制到一边 (cp foo.txt /tmp/foo.txt) 及其参考副本。

之后有其他提交改变了foo.txt 的内容,比如提交abcdef),因此文件现在实际上在 git 中看起来像:

Hello world
How are you doing?
I'm fine, and you?
I'm Ok too

所以实际提出的问题是如何找到提交后,文件foo.txt 看起来与参考副本完全一样,因为它存储在/tmp/foo.txt:它只包含“Hello world”(提交789在我的例子中)

在这种情况下,我相信你应该使用git bisect 命令,给它最后一次提交和第一次(初始提交)的边界,如果项目中有很多提交,运行二进制搜索会快得多而不是遍历文件历史记录中的所有提交。

阅读它here

您应该知道如何根据git bisest 来决定提交是“好”还是“坏”(例如,它是否包含单词“hello”和“world”)

【讨论】:

  • 我相信git bisect 甚至可以接受命令来运行,所以你可以执行git bisect <commit> <commit> diff <file> <file> 或任何语法
  • 谢谢。为此使用 git bisect 是个好主意。
【解决方案2】:

git hash-object path/to/file 将向您显示工作树中文件的 blob id。

git log --no-abbrev --full-history --cc --raw --pretty=format:%H -- path/to/file 将在您历史记录中对该文件的每次更改时转储旧的和新的 blob id。

git log --no-abbrev --full-history --cc --raw --pretty=format:%H -- path/to/file \
| awk '$5==blob' RS='' blob=`git hash-object path/to/file`

将向您显示生成文件的提交。

【讨论】:

    【解决方案3】:

    看来你可以使用git describe

    git describe <sha>
    

    来自git describe 手册页:

    如果给定的对象引用了一个 blob,它将被描述 如&lt;commit-ish&gt;:&lt;path&gt;,这样就可以找到blob 在&lt;commit-ish&gt; 中的&lt;path&gt;,它本身描述了 此 blob 在反向修订遍历中发生的第一次提交 来自 HEAD。

    要获取文件的&lt;sha&gt;,请使用

    git ls-files -s <file>
    

    就像 Adrian Shum 在 cmets 中指出的那样,这只会为您提供文件所在的第一个提交。您可以使用 git log 帮助您找到文件更改的下一个提交,为您提供一系列可能提交。

    更多信息:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-25
      • 2019-12-01
      • 2013-03-18
      • 1970-01-01
      • 2012-12-24
      • 2017-08-15
      • 1970-01-01
      • 2017-10-28
      相关资源
      最近更新 更多