Existe um comando rápido do Git para ver uma versão antiga de um arquivo?

1510

Existe um comando no Git para ver (despejado no stdout ou em $PAGERou $EDITOR) uma versão específica de um arquivo específico?

Mike
fonte
Se você chegou a essa pergunta porque deseja verificar uma versão mais antiga de um arquivo binário (por exemplo, uma imagem), é melhor fazer um checkout do commit antigo, ver o que você precisa ver e voltar ao HEAD. Para isso, faça git checkout <sha1-of-the-commit-you-need>depoisgit checkout HEAD
Homero Esmeraldo

Respostas:

1731

Você pode usar git showcom um caminho da raiz do repositório ( ./ou ../para o caminho relativo):

$ git show REVISION:path/to/file

Substitua REVISIONpor sua revisão real (pode ser um SHA de confirmação do Git, um nome de tag, um nome de filial, um nome de confirmação relativo ou qualquer outra maneira de identificar uma confirmação no Git)

Por exemplo, para visualizar a versão do arquivo <repository-root>/src/main.cde 4 confirmações atrás, use:

$ git show HEAD~4:src/main.c

O Git para Windows requer barras, mesmo em caminhos relativos ao diretório atual. Para mais informações, consulte a página de manual git-show.

mipadi
fonte
5
Isso realmente não parece funcionar - você tentou? Para "git show HEAD: path / to / file.c", recebo o erro "argumento ambíguo".
Mike3
2
Tem que ser o caminho completo, a partir do topo do repo git
richq
20
Se você estiver no Windows, pode ser uma coisa de separador de caminho; se eu git mostrar HEAD: dir \ subdir \ file, recebo o argumento anônimo. Se o git mostrar HEAD: dir / subdir / file, ele funcionará conforme o esperado.
precisa
12
O caminho que você deve fornecer após o: é da raiz do repositório git. (este foi dada abaixo como uma resposta, mas eu acho que foi concebido como um comentário sobre esta resposta)
MatrixFrog
9
Se você quiser vê-lo em uma divisão do Vim para que eles rolem juntos, escrevi um pequeno post mostrando como fazer isso.
Flaviu
257

Fazer isso por data é assim:

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt

Observe que HEAD@{2013-02-25}significa "onde o HEAD estava em 25/02/2013" neste repositório (usando o reflog ), não "o último commit antes de 25-02-2013 neste ramo no histórico".

Jim Hunziker
fonte
5
Impressionante. Economiza muito tempo em vez de ir ao github e olhar para o commit.
Fizer Khan
O "ponto" no caminho do arquivo foi o meu problema. Obrigado!
precisa saber é o seguinte
5
Este comando é útil com masterem vez de HEAD@{2013-02-25}, se você estiver em um ramo
funroll
1
Você pode incluir o tempo, à la git log --since='2016-04-28 23:59:59 +0100'?
dumbledad
7
O fato de essa sintaxe usar o reflog é importante e deve ser destacado fortemente, porque o reflog não contém todos os commits . Veja blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Alice Heaton
113

Se você gosta de GUIs, pode usar o gitk:

  1. inicie o gitk com:

    gitk /path/to/file
    
  2. Escolha a revisão na parte superior da tela, por exemplo, por descrição ou data. Por padrão, a parte inferior da tela mostra o diff dessa revisão (correspondente ao botão de opção "patch").

  3. Para ver o arquivo da revisão selecionada:

    • Clique no botão de opção "árvore". Isso mostrará a raiz da árvore de arquivos nessa revisão.
    • Faça uma busca detalhada no seu arquivo.
Trausti Kristjansson
fonte
7
Isso também funciona com o tig , que é um visualizador de repositórios malditos do git repo.
Matthew G
1
@ Paul Slocum: Pode ser porque esse comando não é um comando convencional, não é o built-in do git. Eu acho que esse comando só funciona no Windows.
Envil
Note que isso só parece funcionar se você iniciar a partir da raiz do seu repositório git.
Marc
Se você quiser verificar contra uma certa revisão com gitk você também pode usar este atalho: gitk REVISION /path/to/file. Isso pode ser útil quando você deseja verificar uma determinada versão, por exemplo.
Christian.D
89

Você também pode especificar um commit hash(muitas vezes também chamado commit ID) com o git showcomando .


Em poucas palavras

git show <commitHash>:/path/to/file


Passo a passo

  1. Mostre o log de todas as alterações para um determinado arquivo com git log /path/to/file
  2. Na lista de mudanças mostrado, que mostra o commit hashtal como commit 06c98...(06c98 ... sendo o hash cometer)
  3. Copie o commit hash
  4. Execute o comando git show <commitHash>:/path/to/fileusando as commit hashetapas 3 e path/to/file1.

Nota: adicionar ./ao especificar um caminho relativo parece importante, ie git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html.

Adrien Be
fonte
1
caso você não saiba o caminho do arquivo, use-o git show <SHA1> --name-onlypara obtê-lo.
Tiina 11/10
este comando op - até mesmo auto concluída da memória - testado em um diretório apagado ... não pode obter mais op do que gg
treyBake
43

Além da resposta de Jim Hunziker ,

você pode exportar o arquivo da revisão como,

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt

Espero que isto ajude :)

Ijas Ameenudeen
fonte
23

Para ver rapidamente as diferenças com as revisões mais antigas de um arquivo:

git show -1 filename.txt > comparar com a última revisão do arquivo

git show -2 filename.txt > comparar com a segunda última revisão

git show -3 fielname.txt > comparar com a última terceira revisão

sachin_ur
fonte
18
Esses comandos mostram as diferenças com a versão atual para mim, mas não mostram o arquivo inteiro.
Jean Paul
18

git log -pmostrará não apenas os logs de confirmação, mas também o diff de cada confirmação (exceto as confirmações de mesclagem). Então você pode pressionar /, digite o nome do arquivo e pressione enter. Pressione nou ppara ir para a ocorrência seguinte / anterior. Dessa forma, você não apenas verá as alterações no arquivo, mas também as informações de confirmação.

Sanbor
fonte
3
Parece git log -pmque também mostraria confirmações de mesclagem.
Sanbor 6/16
2
Você também pode executar git log -p -- filename.txtpara restringir o histórico apenas ao arquivo desejado.
Jean Paul
3

Você pode usar um script como este para despejar todas as versões de um arquivo para separar arquivos:

por exemplo

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Obtenha o script aqui como resposta a outra pergunta semelhante

Brad Parks
fonte
1
git_root, git_log_shortE git_log_message_for_commitestão faltando.
mogsie
Boa pegada! Eu dupliquei esta resposta em 2 pontos diferentes, e apenas removi este e vinculei ao outro, onde as pessoas me falaram sobre isso antes ... obrigado @mogsie!
Brad Parks
Este script é muito útil!
XMAN
3

MANEIRA 1: (prefiro assim)

  1. Encontre o ID de confirmação com:git reflog
  2. Listar arquivos do commit git diff-tree --no-commit-id --name-only -r <commitHash>

exemplo: git diff-tree --no-commit-id --name-only -r d2f9ba4// "d2f9ba4" é o ID de confirmação de "1."

  1. Abra o arquivo necessário com o comando:

git show <commitHash>:/path/to/file

exemplo: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// "Src / ..." é o caminho do arquivo de "2".

MANEIRA 2:

  1. Encontre o ID de confirmação com:git reflog
  2. redefinir com força esse commit: git reset --hard %commit ID%

git reset --hard c14809fa

  1. faça qualquer alteração desnecessária e faça uma nova confirmação no ramo necessário :)
Andrew
fonte
0

Auxiliar para buscar vários arquivos de uma determinada revisão

Ao tentar resolver conflitos de mesclagem, esse auxiliar é muito útil:

#!/usr/bin/env python3

import argparse
import os
import subprocess

parser = argparse.ArgumentParser()
parser.add_argument('revision')
parser.add_argument('files', nargs='+')
args = parser.parse_args()
toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).rstrip().decode()
for path in args.files:
    file_relative = os.path.relpath(os.path.abspath(path), toplevel)
    base, ext = os.path.splitext(path)
    new_path = base + '.old' + ext
    with open(new_path, 'w') as f:
        subprocess.call(['git', 'show', '{}:./{}'.format(args.revision, path)], stdout=f)

GitHub upstream .

Uso:

git-show-save other-branch file1.c path/to/file2.cpp

Resultado: o seguinte contém as versões alternativas dos arquivos:

file1.old.c
path/to/file2.old.cpp

Dessa forma, você mantém a extensão do arquivo para que seu editor não se queixe e possa encontrar facilmente o arquivo antigo ao lado do mais novo.

Ciro Santilli adicionou uma nova foto
fonte
@MickeyPerlstein se você consegue alcançar a mesma interface com uma melhor implementação, sou todo ouvidos.
Ciro Santilli # 24/19
talvez eu não entenda (e se sim, minhas desculpas), mas não é apenas: "git show version: ./ path> new_path"?
Mickey Perlstein
@MickeyPerlstein oi, sim, meu comando gera essa CLI, mas faz um loop em vários arquivos e produz o nome da saída da entrada, para que você não precise digitar muito. Nada revolucionário, é claro, mas conveniente.
Ciro Santilli foi lançado em 26/03/19