是否可以在初始状态下从Git存储库中检索一组文件

时间:2017-09-26 13:10:18

标签: git initialization commit

我有一个git存储库,其中包含许多(.tex)个文件,这些文件已在不同的时间/提交时添加。我想复制一个临时目录,因为它们处于初始状态(当它们被添加到存储库时)。重点是向某人展示他们在完成一些工作之前看起来有多丑:)

有可能吗?

3 个答案:

答案 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处于最后状态..希望这会有所帮助。