Получить все версии файла из одной ветки
Если в 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) он чувствует себя супер хаки.
Есть ли лучший способ сделать это, возможно, лучше использовать API Git?
2 ответа
Не лучшее решение, но это одна из возможностей
Если это единственная вещь, которую вы пытаетесь сделать, вы можете попробовать это с помощью следующего сценария, но он использует фарфор Git версии 1.9.4, так что это определенно не надежное и надежное решение, так как зависит от того, какую версию 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 и будут более обратными и прямыми. совместимы.
Документация
Я бы предложил использовать 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