我有一个git存储库,其中包含许多(.tex
)个文件,这些文件已在不同的时间/提交时添加。我想复制一个临时目录,因为它们处于初始状态(当它们被添加到存储库时)。重点是向某人展示他们在完成一些工作之前看起来有多丑:)
有可能吗?
答案 0 :(得分:1)
当然这是可能的,但是当它完成时你可能希望你只是选择一些样本来手动提取。
首先,您需要确定“文件的第一版”。我能想到的最简单的方法是使用git log
- 这对于编写脚本来说不是很好,但是......
git log --diff-filter=A --name-only --format=' :COMMIT: %H' --all -- *.tex **/*.tex
格式字符串以您合理预期不会成为文件路径的一部分开头。我已经在末尾添加了一些pathspec参数,这应该将输出限制为仅显示.tex
个文件。这可能是两种方式中效率更高的效率;但如果它引起问题,我会在下面的脚本中提到一个替代方案......
现在您有一份提交列表。对于每个提交,您会看到提交ID(哈希),后跟提交中创建的文件列表。
因此,您可以使用您喜欢的任何类型的脚本处理该输出。我使用perl来做这类事情,所以它就像是
my $sha = 0;
while(<>) {
chomp;
next if m/^$/;
if ( m/^ :COMMIT: ([0-9a-f]*)$/ ) {
$sha = $1;
} else {
system("git --work-tree=/path/to/temp/dir checkout $sha -- $_");
}
}
请注意,如果向初始git log
命令添加路径参数不起作用 - 或者您选择不这样做 - 您可以将else
更改为此elsif
:
my $sha = 0;
while(<>) {
chomp;
next if m/^$/;
if ( m/^ :COMMIT: ([0-9a-f]*)$/ ) {
$sha = $1;
} elsif ( m/\.tex$/ ) {
system("git --work-tree=/path/to/temp/dir checkout $sha -- $_");
}
}
如果要在perl脚本中包含git log
命令,则如下所示:
my $sha = 0;
my @list = `git log --diff-filter=A --name-only --format=' :COMMIT: %H' --all -- *.tex **/*.tex`;
foreach(@list) {
chomp;
next if m/^$/;
if ( m/^ :COMMIT: ([0-9a-f]*)$/ ) {
$sha = $1;
} elsif ( m/\.tex$/ ) {
system("git --work-tree=/path/to/temp/dir checkout $sha -- $_");
}
}
答案 1 :(得分:0)
首次将提交添加到存储库时,您应首先找到提交,为此,您可以运行:
git log <PATH_TO_YOUR_FILES> | tail
现在复制(部分)写在提交消息之上的提交哈希
commit 4adbcaf93a0805fd2c6fbcb6b929c3d438ce7c07
现在,您可以通过运行以下命令获取该提交中的文件:
git cat-file -p 4adbcaf:<PATH_TO_YOUR_FILE>
总之,您可以使用像这样的bash脚本将一组文件恢复到初始提交状态:
# git-restore-initial-state.sh
#!/bin/bash
mkdir -p temp
for f in "$@"
do
commit=$(git log --pretty=%H "$f" | tail -1)
git cat-file -p "$commit:$f" > "temp/$f"
done
保存脚本并运行它:
git-restore-initial-state.sh file_a file_b
编辑:感谢ElpieKay帮助他简化脚本。
答案 2 :(得分:0)
获取每个文件的第一个提交ID / desc(使用“.tex”):
for f in *.tex; do git log --oneline "$f" | tail -1; done
您可以使用以下内容查看初始提交完整消息:
for f in *.tex; do git show $(git log --oneline "$f" | tail -1 | awk '{print$1}'); done
要复制temp目录中的初始文件,可以使用下一个脚本:
$ mkdir ../temp
$ ls *.tex > ../temp/listOfFiles.txt
$ cat ../temp/listOfFiles.txt | while read line; do git checkout $(git log --oneline "$line" | tail -1 | awk '{print$1}'); cp "$line" ../temp/"$line"; git checkout master; done
$ git status
最后,repo处于最后状态..希望这会有所帮助。