等效于git的“ hg cat”或“ svn cat”


84

我想提取git存储库中保存的文件的最新版本的副本,并将其传递到脚本中进行某些处理。使用svn或hg时,我只使用“ cat”命令:

按指定版本打印指定文件。如果未给出修订,则使用工作目录的父目录;如果未签出任何修订,则提示。

(来自hg文档中对hg cat的描述)

用git执行此操作的等效命令是什么?


4
我的最终解决方案是首先使用“ git ls-files --full-name <filepath>”获取相对于存储库顶部的完整路径,然后使用“ git show HEAD:<full filepath>”
Richard Boulton


Answers:


113
git show rev:path/to/file

转速是修订。

有关git和svn命令的比较,请参见http://git.or.cz/course/svn.html


1
这对我有用,是的!(使用HEAD作为修订版)我认为我需要使用相对于存储库顶部的路径,这有点麻烦,但是可行。
理查德·布尔顿

@Richard Boulton:如果使用制表符
补全,

@pimlottc在没有./的情况下对我来说工作正常,-可能取决于git版本
Trejkaz

9

您可以像这样运行“ git cat-file”:

$ git cat-file blob v1.0:path/to/file

您可以在其中用分支,标记或提交所需的SHA替换“ v1.0”,然后在存储库中用相对路径替换“ path / to / file”。如果需要,还可以传递“ -s”以查看内容的大小。

尽管前面提到的“ show”将做同样的事情,但它可能更接近于您习惯的“ cat”命令。


6

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.

这似乎不起作用:运行“ git show next〜1:README”会产生致命错误:模棱两可的参数“ next〜1:README”:未知的修订版或路径不在工作树中。使用“-”将路径与修订内容分开
理查德·布尔顿

1
您是否有一个名为“下一个”的分支?如果要当前分支,请使用“ HEAD”。
Andrew Aylett

3

也可以使用分支名称(例如第一个p中的HEAD):

git show $branch:$filename



1

似乎没有直接替代品。此博客条目详细说明了如何执行等效操作,方法是确定最新提交,然后确定该提交中文件的哈希,然后将其转储出去。

git log ...
git ls-tree ...
git show -p ...

(博客条目具有拼写错误,并在命令中使用以上内容svn


尽管有错字,博客条目还是很有帮助的。
理查德·布尔顿

0

没有一个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 );
}

0

对于使用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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.