gitリポジトリに保持されているファイルの最新バージョンのコピーを抽出し、それをスクリプトに渡して処理したいと思います。svnまたはhgでは、「cat」コマンドを使用するだけです。
指定されたリビジョンのファイルをそのまま印刷します。リビジョンが指定されていない場合は、作業ディレクトリの親が使用されます。リビジョンがチェックアウトされていない場合は、ヒントが使用されます。
(これは、hgドキュメントのhg catの説明からのものです)
gitでこれを行うための同等のコマンドは何ですか?
gitリポジトリに保持されているファイルの最新バージョンのコピーを抽出し、それをスクリプトに渡して処理したいと思います。svnまたはhgでは、「cat」コマンドを使用するだけです。
指定されたリビジョンのファイルをそのまま印刷します。リビジョンが指定されていない場合は、作業ディレクトリの親が使用されます。リビジョンがチェックアウトされていない場合は、ヒントが使用されます。
(これは、hgドキュメントのhg catの説明からのものです)
gitでこれを行うための同等のコマンドは何ですか?
回答:
git show rev:path/to/file
ここで、revはリビジョンです。
gitコマンドとsvnコマンドの比較については、http://git.or.cz/course/svn.htmlを参照してください。
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.
githubにあるgitcatシェルスクリプトを書きました
直接的な代替手段はないようです。このブログエントリでは、最新のコミットを決定し、そのコミット内のファイルのハッシュを決定し、それをダンプすることによって、同等の方法を詳しく説明しています。
git log ...
git ls-tree ...
git show -p ...
(ブログエントリにはタイプミスがあり、コマンドで上記を使用しますsvn
)
git show
(私がそうするかもしれないが)、出力の上部からメタデータの断片を取得しない方法を見つけることができないので、提案のどれも本当に満足しません。cat(1)の精神は、内容を表示することだけです。これ(以下)は、ファイル名とオプションの番号を取ります。数は、どのようにコミットを戻したいかです。(そのファイルを変更したコミット。ターゲットファイルを変更しないコミットはカウントされません。)
gitcat.pl filename.txt
gitcat.pl -3 filename.txt
は、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 );
}
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