我想从git仓库中提取最新版本的文件副本,并将其传递到脚本进行处理。对于svn或hg,我只需使用“cat”命令:
那么在git中,如何执行相同的操作呢?
(这是来自hg文档中hg cat的描述)按给定修订版打印指定的文件。如果没有给出修订版,则使用工作目录的父级,如果没有检出修订版,则使用tip。
那么在git中,如何执行相同的操作呢?
(这是来自hg文档中hg cat的描述)按给定修订版打印指定的文件。如果没有给出修订版,则使用工作目录的父级,如果没有检出修订版,则使用tip。
有一个名为 "git cat-file" 的命令,可以这样运行:
$ git cat-file blob v1.0:path/to/file
你可以将 'v1.0' 替换为所需的分支、标签或提交的SHA值,然后将 'path/to/file' 替换为仓库中文件的相对路径。如果需要,你也可以传递 '-s' 参数来查看内容大小。
这个命令可能更接近你所熟悉的 'cat' 命令,虽然前面提到的 'show' 命令也会完成类似的工作。
git show
是您需要查找的命令。根据文档:
git show next~10:Documentation/README
Shows the contents of the file Documentation/README as they were
current in the 10th last commit of the branch next.
同时也适用于分支名称(例如第一个段落中的HEAD):
git show $branch:$filename
似乎没有一个直接的替代方法。这篇博客文章详细介绍了如何通过确定最新提交,然后确定该提交中文件的哈希值,最后将其转储来实现等效操作。
git log ...
git ls-tree ...
git show -p ...
(博客文章有错别字,并使用上述命令svn
)
对于使用bash的人来说,以下是一个有用的函数:
gcat () { if [ $# -lt 1 ]; then echo "Usage: $FUNCNAME [rev] file"; elif [ $# -lt 2 ]; then git show HEAD:./$*; else git show $1:./$2; fi }
将它放在你的.bashrc
文件中(除了gcat
之外,你可以使用任何名称)。
示例用法:
> gcat
Usage: gcat [rev] file
或者
> gcat subdirectory/file.ext
或者
> gcat rev subdirectory/file.ext
没有一个git show
的建议真正满足我的需求,因为(尽我所能地尝试),我找不到一种方法来避免在输出顶部获取元数据垃圾。cat(1)的精神只是显示内容。
下面的代码接受一个文件名和一个可选的数字。这个数字表示你想要回溯多少次提交。(只计算那些改变了该文件的提交。没有改变目标文件的提交不计入其中。)
gitcat.pl filename.txt
gitcat.pl -3 filename.txt
显示filename.txt文件的最新提交内容以及之前3次提交的内容。
#!/usr/bin/perl -w
use strict;
use warnings;
use FileHandle;
use Cwd;
# Have I mentioned lately how much I despise git?
(my $prog = $0) =~ s!.*/!!;
my $usage = "Usage: $prog [revisions-ago] filename\n";
die( $usage ) if( ! @ARGV );
my( $revision, $fname ) = @ARGV;
if( ! $fname && -f $revision ) {
( $fname, $revision ) = ( $revision, 0 );
}
gitcat( $fname, $revision );
sub gitcat {
my( $fname, $revision ) = @_;
my $rev = $revision;
my $file = FileHandle->new( "git log --format=oneline '$fname' |" );
# Get the $revisionth line from the log.
my $line;
for( 0..$revision ) {
$line = $file->getline();
}
die( "Could not get line $revision from the log for $fname.\n" )
if( ! $line );
# Get the hash from that.
my $hash = substr( $line, 0, 40 );
if( ! $hash =~ m/ ^ ( [0-9a-fA-F]{40} )/x ) {
die( "The commit hash does not look a hash.\n" );
}
# Git needs the path from the root of the repo to the file because it can
# not work out the path itself.
my $path = pathhere();
if( ! $path ) {
die( "Could not find the git repository.\n" );
}
exec( "git cat-file blob $hash:$path/'$fname'" );
}
# Get the path from the git repo to the current dir.
sub pathhere {
my $cwd = getcwd();
my @cwd = split( '/', $cwd );
my @path;
while( ! -d "$cwd/.git" ) {
my $path = pop( @cwd );
unshift( @path, $path );
if( ! @cwd ) {
die( "Did not find .git in or above your pwd.\n" );
}
$cwd = join( '/', @cwd );
}
return join( '/', map { "'$_'"; } @path );
}