Como diferenciar um commit com seu pai?


460

Além de escrever um alias ou script, existe um comando mais curto para obter o diff para um commit específico?

git diff 15dc8^..15dc8

Se você fornecer apenas o único ID de confirmação git diff 15dc8, será diferente desse commit contra HEAD.


O mais legal disso é que isso funcionaria com o "git difftool", usando as ferramentas para mostrar o diff.
orip 6/07/10

Para referência, a resposta a esta outra questão ilustra como você pode configurar um apelido bash-alimentado para simplificar o acima: stackoverflow.com/questions/3321492/...
Nick

Respostas:


641

Use git show $COMMIT. Ele mostrará a mensagem de log para o commit e o diff desse commit específico.


45
Pena que não pode usar o difftool :(
orip

1
@orip, você sempre pode definir GIT_EXTERNAL_DIFF para um script que faça a mesma coisa que seu difftool.
slacy

7
Eu prefiro a resposta de JakubNarebski, como a expressão dada comprometer não irá funcionar em muitos contextos: stackoverflow.com/a/449128/992887
RichVel

1
Se não houver diff mostrado, provavelmente há mudanças reais, como para uma mala comprometer
Devin G Rhode

6
@PTWithy: A pergunta era: "Existe um comando mais curto para obter o diff para um commit específico?", Que esta pergunta responde.
Mipadi

439

Usar:

git diff 15dc8^!

como descrito no seguinte fragmento da página de manual git-rev-parse (1) (ou na página de manual moderna git gitrevisions (7) ):

Existem duas outras atalhos para nomear um conjunto formado por uma confirmação e sua confirmação pai. A notação r1 ^ @ significa todos os pais de r1. r1 ^! inclui commit r1, mas exclui todos os seus pais.

Isso significa que você pode usar 15dc8^!como uma abreviação para 15dc8^..15dc8qualquer lugar do git onde as revisões são necessárias. Para o comando diff,git diff 15dc8^..15dc8 entende-se como git diff 15dc8^ 15dc8, o que significa a diferença entre o pai de commit ( 15dc8^) e commit ( 15dc8).

Nota : a descrição na página de git-rev-parse(1)manual fala sobre intervalos de revisão , onde ele também precisa trabalhar para confirmações de mesclagem, com mais de um pai. Então r1^!é " r1 --not r1^@" ie " r1 ^r1^1 ^r1^2 ..."


Além disso, você pode usar git show COMMITpara obter a descrição e o diff de uma confirmação. Se você quiser apenas diff, você pode usargit diff-tree -p COMMIT


7
Esta deve ser a resposta aceita, é muito melhor. No entanto, a última sentença do extrato git-rev-parse é bastante confusa - parece que significa 'intervalo do pai deste commit para esse commit'.
RichVel

1
@ RichVel: é um pouco confuso porque tenta descrever também a situação em que o commit possui mais de um pai (é um commit de mesclagem). r1 ^! funciona como esperado também então.
Jakub Narębski

@ JakubNarębski: bom ponto, talvez você possa editar sua resposta para resumir sua compreensão dos casos monoparentais e multiparentais - declarações separadas sobre cada um podem ser mais fáceis de entender.
RichVel

1
@ JakubNarębski: sim, muito melhor! Agora eu uso esse atalho o tempo todo - obrigado.
RichVel

1
A ^!notação abreviada pai funciona corretamente com difftool para confirmações normais, mas a diferença é revertida para confirmações de mesclagem. Por quê então?
hIpPy

56

Se você sabe há quanto tempo, pode tentar algo como:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

As confirmações anteriores funcionam mais ou menos assim:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

Existem várias maneiras de especificar confirmações:

# Great grandparent
git show HEAD~3

Vejo esta página para detalhes .


2
HEAD ^ 2 não é o avô; se HEAD ^ 1 é papai, HEAD ^ 2 é mamãe. Use HEAD ~ 2 para o pai do papai.
Binarian

11

Como o @mipadi aponta, você pode usar git show $COMMIT, mas isso também mostra alguns cabeçalhos e a mensagem de confirmação. Se você quiser um diff direto, usegit show --pretty=format:%b $COMMIT .

Obviamente, essa não é uma mão muito curta, então estou mantendo esse alias no meu .gitconfig

    [alias]
      sd = show --pretty=format:%b

Isso me permite usar git sd $COMMITpara mostrar diff .


1
Este alias pode incluir --color o que o torna mais fácil de ler: sd = mostrar --color --pretty = formato:% b
RichVel

@RichVel Indeed! Muito bom ponto. Se você tem as cores ativadas por padrão no git, você não precisará dessa opção. É o que eu normalmente faço.
Øystein Steimler

5

Muitos dos exemplos mencionados (por exemplo git diff 15dc8^!, ou git diff 15dc8^..15dc8) não funcionam se você estiver usando o zsh e tiver o extendedglobconjunto de opções. Você pode corrigi-lo de uma das três maneiras a seguir:

  1. unsetopt extendedglob (e / ou remova-o de .zshrc)

  2. setopt NO_NOMATCH (e / ou defina em .zshrc)

  3. escapar do sinal de intercalação e bater sempre com uma barra invertida, por exemplo git diff 15dc8\^\!



2

A solução de Paulo acima fez o que eu esperava.

$ git diff HEAD^1

Além disso, é útil adicionar aliases, como os hobs mencionados, se você colocar o seguinte na seção [alias] do seu arquivo ~ / .gitconfig, poderá usar a abreviação para visualizar o diff entre head e anterior.

[alias]
    diff-last = diff HEAD^1

Então, executando $ git diff-last você obterá seu resultado. Observe que isso também incluirá quaisquer alterações que você ainda não tenha confirmado, bem como a diferença entre confirmações. Se você deseja ignorar as alterações que ainda não foram confirmadas, use diff para comparar o HEAD com o pai diretamente:

$ git diff HEAD^1 HEAD

0

Usa aliases, portanto, não responde exatamente à sua pergunta, mas acho úteis para fazer o que você pretende ...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.