从单个分支获取文件的所有版本

时间:2014-08-01 18:50:07

标签: git file version git-plumbing

鉴于git存储库中有一个分支,如何获取文件的所有版本?最终所需的输出是每个版本一个新的输出文件(尽管将所有版本打印到STDOUT也很好,只要它很容易确定每个版本的范围)。

这是我目前正在使用的内容:

branch=master
filename=...whatever...

myids=( $(git rev-list --objects $branch -- $filename | grep $filename | perl -e 'for (<>) { print substr($_, 0, 40) . "\n"; }') )

for (( i=0,j=1; i < ${#myids[@]}; i++,j++ )) 
    do
        echo $i $j
        name="output_$j.txt"
        git cat-file -p ${myids[$i]} > $name
    done

解释我正在做的事情:

  • 使用rev-list查找相关的哈希值
  • 删除提交和树的哈希,只留下文件的哈希值(这些行也包含文件名)
  • 删除文件名
  • 通过cat-file运行哈希并生成输出文件

我遇到的两个主要问题是1)它不健全,因为grep可能有误报,我不确定它是否会跟随文件重命名, 2)感觉超级hacky。

有没有更好的方法来做到这一点,也许更好地利用git的API?

2 个答案:

答案 0 :(得分:2)

不是最佳解决方案,但它是一种可能性

如果这只是您尝试做的一次性事情,您可以尝试使用以下脚本,但它使用的是1.9.4版本的Git瓷器,所以它绝对不是一个强大,可靠的解决方案,因为它取决于您使用的Git版本:

#!/bin/bash
mkdir temp
filepath=osx/.gitconfig

for sha in $(git log --format="%H" $filepath); do
  git show $sha:$filepath > temp/$sha.file
done

它只是使用git log来查找修改文件的所有提交:

$ git log --format="%H" osx/.gitconfig
338243aa6b68edad1dc3b2eebf66e108e9a4d685
7a4667138a519691386940ac23f9c8271ce14c77
475593a612141506f59a141e38b8c6a3a2917f85
03fa0711032cfdfc37fb431d60567ef22d75c7e5
3f7d8f0fc7e1d7a614f2aef8f53947ec2ce61296
c5fef8fccef3fc13f9dea17db209f2ceaab70002
287dadd8bcaf7e9197c6a16d57d3bacb72a41812
1f34ee1ab6965635a8f412bf3387f9dfdf197a1d

然后使用<revision>:<filepath>语法输出该修订版本的文件版本。

git log有时可以简化您的图表历史记录,因此您甚至可能希望将--full-history标记传递给git log,但我并不确定它是否会这个特定用例所必需的。

这会如何更好地重命名文件?您可能需要让脚本更加智能地跟踪它,以便使用正确的文件路径。

然而,我再次强调这不是最佳解决方案,更好的解决方案是使用Git管道命令,因为他们不会成为所以依赖于Git版本,并且会更加向后兼容。

文档

答案 1 :(得分:1)

我建议在文件本身上使用git-log,而不是git-rev-list

#!/bin/bash

filename=...whatever...

i=1
for hash in `git log --pretty=format:%H -- $filename`
do
    git show $hash:$filename > output_$i.txt
    ((i++))
done