3

给定 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?

4

2 回答 2

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 版本,并且会更加向后和向前兼容的。

文档

于 2014-08-01T20:14:01.557 回答
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
于 2014-08-01T21:06:29.220 回答