Tương đương trong git của “hg cat” hoặc “svn cat”


84

Tôi muốn trích xuất bản sao của phiên bản mới nhất của tệp được lưu trữ trong kho lưu trữ git và chuyển nó vào tập lệnh để xử lý. Với svn hoặc hg, tôi chỉ sử dụng lệnh "cat":

In các tệp được chỉ định như chúng ở bản sửa đổi đã cho. Nếu không có bản sửa đổi nào được đưa ra, thì thư mục gốc của thư mục làm việc sẽ được sử dụng hoặc mẹo nếu không có bản sửa đổi nào được kiểm tra.

(đó là từ mô tả của mèo hg trong tài liệu hg)

Lệnh tương đương để thực hiện việc này với git là gì?


4
Giải pháp cuối cùng của tôi trước tiên là sử dụng "git ls-files --full-name <filepath>" để lấy đường dẫn đầy đủ liên quan đến đầu kho lưu trữ và sau đó là "git show HEAD: <full filepath>"
Richard Boulton


Câu trả lời:


113
git show rev:path/to/file

Nơi rev là sửa đổi.

Xem http://git.or.cz/course/svn.html để so sánh các lệnh git và svn.


1
Điều này làm việc cho tôi, yay! (Sử dụng HEAD làm bản sửa đổi) Tôi nghĩ rằng tôi cần sử dụng đường dẫn liên quan đến phần trên cùng của kho lưu trữ, điều này hơi khó, nhưng khả thi.
Richard Boulton

@ Richard Boulton: đây là ít đau đớn nếu sử dụng tab completition
ks1322

@pimlottc làm việc tốt cho tôi mà không có sự ./ - có thể phụ thuộc vào phiên bản git
Trejkaz

9

có "git cat-file" mà bạn có thể chạy như sau:

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

nơi bạn có thể thay thế 'v1.0' bằng nhánh, thẻ hoặc cam kết SHA bạn muốn và sau đó 'đường dẫn / đến / tệp' bằng đường dẫn tương đối trong kho lưu trữ. Bạn cũng có thể chuyển '-s' để xem kích thước của nội dung nếu bạn muốn.

có thể gần giống với các lệnh 'mèo' mà bạn quen dùng, mặc dù 'chương trình' đã đề cập trước đó sẽ làm được nhiều điều tương tự.


6

git showlà lệnh bạn đang tìm kiếm. Từ tài liệu:

   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.

Điều đó dường như không hoạt động: chạy "git show next ~ 1: README" tạo ra đối số không rõ ràng: "next ~ 1: README": bản sửa đổi không xác định hoặc đường dẫn không có trong cây làm việc. Sử dụng '-' để tách đường dẫn từ các phiên bản
Richard Boulton

1
Bạn có nhánh nào tên là 'tiếp theo' không? Nếu bạn muốn nhánh hiện tại, hãy sử dụng 'HEAD' để thay thế.
Andrew Aylett

3

Cũng làm việc với tên chi nhánh (như HEAD ở p thứ nhất):

git show $branch:$filename


2

Tôi đã viết một script git cat shell, có trên github


1
Xem mã cho điều đó rất hữu ích, mặc dù tôi muốn có một tập lệnh python độc lập và không cần tất cả các tính năng của git cat. Cảm ơn.
Richard Boulton

1

Dường như không có sự thay thế trực tiếp . Mục blog này trình bày chi tiết cách thực hiện điều tương tự bằng cách xác định cam kết mới nhất , sau đó xác định hàm băm cho tệp trong cam kết đó và sau đó kết xuất nó.

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

(mục blog có lỗi chính tả và sử dụng ở trên với lệnh svn)


Mục nhập blog rất hữu ích, bất chấp lỗi chính tả.
Richard Boulton

0

Không có git showđề xuất nào thực sự thỏa mãn bởi vì (cố gắng hết sức có thể), tôi không thể tìm ra cách nào để không nhận được phần mềm siêu dữ liệu từ đầu đầu ra. Tinh thần của mèo (1) là chỉ để hiển thị các nội dung. Điều này (bên dưới) có một tên tệp và một số tùy chọn. Con số là số lượng cam kết bạn muốn quay lại. (Các cam kết đã thay đổi tệp đó. Các cam kết không thay đổi tệp đích không được tính.)

gitcat.pl filename.txt
gitcat.pl -3 filename.txt

hiển thị nội dung của filename.txt kể từ lần cam kết mới nhất của filename.txt và nội dung từ 3 lần cam kết trước đó.

#!/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

Đối với những người sử dụng bash, sau đây là một chức năng hữu ích:

gcat () { if [ $# -lt 1 ]; then echo "Usage: $FUNCNAME [rev] file"; elif [ $# -lt 2 ]; then git show HEAD:./$*; else git show $1:./$2; fi }

Đặt nó vào .bashrctệp của bạn (bạn có thể sử dụng bất kỳ tên nào bạn thích khác gcat.

Ví dụ sử dụng:

> gcat
Usage: gcat [rev] file

hoặc là

> gcat subdirectory/file.ext

hoặc là

> gcat rev subdirectory/file.ext
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.