Еквівалентно git "hg cat" або "svn cat"


84

Я хочу витягти копію останньої версії файлу, що зберігається у сховищі git, і передати його у сценарій для деякої обробки. З svn або hg я просто використовую команду "cat":

Роздрукуйте вказані файли такими, якими вони були на даній версії. Якщо жодної редакції не вказано, використовується батьківський робочий каталог або підказка, якщо жодна редакція не перевірена.

(це з опису hg cat в документації hg)

Яка еквівалентна команда для цього з git?


4
Моїм остаточним рішенням було спочатку використовувати "git ls-files --full-name <filepath>", щоб отримати повний шлях відносно верхньої частини сховища, а потім "git show HEAD: <full filepath>"
Річард Боултон


Відповіді:


113
git show rev:path/to/file

Де rev - це перегляд.

Див. Http://git.or.cz/course/svn.html для порівняння команд git та svn.


1
Це працює для мене, так! (Використовуючи HEAD як ревізію) Я думаю, мені потрібно використовувати шлях відносно верхньої частини сховища, що трохи болить, але є працездатним.
Річард Боултон,

@Richard Boulton: це менш боляче, якщо використовувати доповнення вкладок
ks1322

@pimlottc у мене чудово працював і без ./ - може залежати від версії git
Trejkaz

9

є "git cat-файл", який ви можете запустити так:

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

де ви можете замінити 'v1.0' на потрібну вам гілку, тег або коміт SHA, а потім 'шлях / до / файлу' відносним шляхом у сховищі. Ви також можете передати "-s", щоб побачити розмір вмісту, якщо хочете.

може бути ближче до звичених вам команд "кішка", хоча раніше згадане "шоу" буде робити майже те саме.


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

Також працюйте з іменами гілок (наприклад, HEAD у першому p):

git show $branch:$filename



1

Здається, прямої заміни немає. Цей запис у блозі докладно розповідає, як зробити еквівалент, визначивши останній коміт, потім визначивши хеш для файлу в цьому коміті, а потім скинувши його.

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

(запис у блозі має друкарські помилки та використовує вищезазначене з командою svn)


Запис у блозі був корисним, незважаючи на помилки.
Річард Боултон,

0

Жодна з git showпропозицій по-справжньому не задовольняє, тому що (намагайтеся, як міг), я не можу знайти спосіб не отримати метадані, що утворюються вгорі результату. Дух кота (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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.