Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以在Git存储库的初始状态下检索一组文件_Git_Initialization_Commit - Fatal编程技术网

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

是否可以在Git存储库的初始状态下检索一组文件,git,initialization,commit,Git,Initialization,Commit,我有一个git存储库,其中包含许多(.tex)文件,这些文件是在不同的时间/提交时添加的。我想将它们复制到一个临时目录中,因为它们处于初始状态(当它们被添加到存储库时)。重点是在做一些工作之前,向某人展示他们有多丑:) 有可能吗?您应该在首次将提交添加到存储库时首先找到提交,为此,您可以运行: git log <PATH_TO_YOUR_FILES> | tail 现在,您可以通过运行以下命令获得提交中的文件: git cat-file -p 4adbcaf:<PATH_TO

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


有可能吗?

您应该在首次将提交添加到存储库时首先找到提交,为此,您可以运行:

git log <PATH_TO_YOUR_FILES> | tail
现在,您可以通过运行以下命令获得提交中的文件:

git cat-file -p 4adbcaf:<PATH_TO_YOUR_FILE>
保存脚本并运行它:

git-restore-initial-state.sh file_a file_b


编辑:感谢他在简化脚本方面的帮助。

当然有可能,但在完成时,您可能希望您只是选择了几个样本进行手动提取

因此,首先,您需要确定“文件的第一个版本”。我能想到的最简单的方法是使用
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 -- $_");
  }
}
如果希望在perl脚本中包含
git log
命令,则如下所示:

# 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
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 -- $_");
  }
}
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 -- $_");
  }
}

要获取每个文件的第一个提交ID/desc(带“.tex”):

您可以使用以下方法查看初始提交完整消息:

for f in *.tex; do git show $(git log --oneline "$f" | tail -1 | awk '{print$1}'); done
要在临时目录中复制初始文件,可以使用下一个脚本:

$ 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

最后,回购处于最后状态。。希望这有帮助。

这就是如何将其中一个复制到工作树的方法。OP询问了一种将所有这些文件复制到临时目录的方法。用这种方法挑选一些样本可能会更好地利用时间,但实际上并不能解决问题question@MarkAdelsberger谢谢Mark,我明白你的意思了,用一个脚本编辑,它可以恢复一组文件,复制到临时目录并将其恢复到其头部state@MahdiDibaiee我可以给你一些建议来改进你的剧本吗
git log--pretty=%H--path_to_file
可以获取更改此文件的所有提交
git cat file-p commit:path_to_file
可以打印提交文件的内容。因此,您可以使用这两个命令简化脚本。
git cat file-p“$commit:$f”>“temp/$f”
命令导致错误
fatal:不是有效的对象名⟨承诺⟩:⟨档案⟩
@DenisBitouzé您能分享一下您执行的确切命令吗?可能有助于调试脚本。我已经在虚拟存储库上测试过它,但可能是一个边缘案例。另一方面,您是否尝试手动查找文件的提交以查看是否成功?我在
temp
目录中获得的文件与Git存储库中的当前版本相同。我刚刚完成了第二次测试,目前运行良好。。确保您的回购在第一个代码中更新,我想
%H
之后的后引号应该是(正常)引号。除此之外,您的解决方案似乎有效,但不幸的是,它捕获了太多的文件:我想将其仅限于
.tex
文件。修复了引号,并添加了一些选项以过滤非
.tex
文件。效果很好。如果将所有内容都收集到Perl脚本中,而不是在第一个命令上管道化,则会更好:)
for f in *.tex; do git show $(git log --oneline "$f" | tail -1 | awk '{print$1}'); done
$ 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