Como “git show” um commit de mesclagem com saída diff combinada, mesmo quando todos os arquivos alterados concordam com um dos pais?

186

Depois de fazer uma mesclagem "simples" (uma sem conflitos), git showgeralmente mostra apenas algo como

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

Isso ocorre porque, para mesclagens, git showusa o formato diff combinado que omite arquivos que concordam com qualquer uma das versões pai.

Existe uma maneira de forçar o git a mostrar ainda todas as diferenças no modo diff combinado?

Doing git show -mmostrará as diferenças (usando diffs em pares entre as versões nova e principal, respectivamente), mas eu preferiria ter isso com as diferenças marcadas por +/- nas respectivas colunas, como no modo combinado.

Tilman Vogel
fonte
1
@ Tilman Vogel: por favor, revise a resposta aceita - Parece que existem respostas melhores
Jayan
1
@ Jayan Embora as outras respostas sejam mais populares porque contêm dicas úteis, elas na verdade não se aproximam mais do meu problema, pois fazem apenas diferenças nos dois sentidos. Eu estava procurando um diferencial de três vias.
Tilman Vogel

Respostas:

-3

Não, não há como fazer isso git show. Mas certamente seria bom às vezes, e provavelmente seria relativamente fácil de implementar no código-fonte git (afinal, você só precisa dizer a ele para não aparar o que acha que é saída estranha), então o patch deve ser feito provavelmente seria aceito pelos mantenedores do git.

Tenha cuidado com o que você deseja; mesclar uma ramificação com uma alteração de uma linha que foi bifurcada há três meses ainda terá uma diferença enorme em relação à linha principal e, portanto, essa diferença completa seria quase completamente inútil. É por isso que o git não mostra isso.

apenwarr
fonte
12
Por favor, não diga "não há como fazer isso" da maneira mais clara possível - veja outras respostas. Isso é muito enganador de se dizer.
kgadek
1
git show HEAD ^ ... HEAD; # por @ solução de hesham_EE.
Michael Dimmitt
git show HEAD ~ 1 ... HEAD ~ 0 - somente nome; # melhor sintaxe. Para iteração de pr.
Michael Dimmitt 10/10
256

Veja a mensagem de confirmação:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

observe a linha:

Merge: fc17405 ee2de56

pegue esses dois IDs de confirmação e inverta-os. então, para obter o diff que você deseja, faça:

git diff ee2de56..fc17405

para mostrar apenas os nomes dos arquivos alterados:

git diff --name-only ee2de56..fc17405

e para extraí-los, você pode adicionar isso ao seu gitconfig:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

use-o fazendo:

git exportfiles ee2de56..fc17405 /c/temp/myproject
rip747
fonte
Obrigado pela sugestão, mas acho que não resolve o meu problema. Devido à marcação e formatação limitadas dos comentários, adicionei meu comentário à sua resposta. Desculpe por isso! Precisa ser revisado por pares até visível.
Tilman Vogel
6
Parece que minha edição foi recusada. Em resumo: seu diff não mostra quais adições vêm de qual ramificação. E você não pode distinguir se as alterações foram adicionadas no segundo ou removidas no primeiro ramo.
Tilman Vogel
45
Uma solução melhor é git diff fc17405...ee2de56- isso mostrará todas as alterações no ee2de56 acessíveis a partir de confirmações no fc17405, que acredito ser o que você deseja. Observe os 3 pontos em vez de dois.
Kris Nuttycombe
1
@KrisNuttycombe 3 pontos e a ordem. E seu comentário é o que eu estava procurando, que eu acho que é mais parecido com o que o OP queria.
Izkata
@KrisNuttycombe Isso de alguma forma não funciona git log, o que ainda mostra todos os commits, como a ..variante. ..e ...faça o mesmo por log, mas diffeles são diferentes !? Como obtenho uma lista de confirmações que foram mescladas neste ramo?
Rudie
77

Uma solução melhor (mencionada por @KrisNuttycombe):

git diff fc17405...ee2de56

para o commit de mesclagem:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

para mostrar todas as alterações ee2de56acessíveis a partir de confirmações fc17405. Observe a ordem dos hashes de confirmação - é a mesma mostrada nas informações de mesclagem:Merge: fc17405 ee2de56

Observe também os 3 pontos em ...vez de dois !

Para uma lista de arquivos alterados, você pode usar:

git diff fc17405...ee2de56 --name-only
CodeManX
fonte
Era exatamente isso que eu buscava +1.
precisa saber é o seguinte
Na verdade, isso mostra o resultado de um conflito de mesclagem, enquanto a outra resposta não.
Pod
12

Você pode criar uma ramificação com HEAD definido como uma confirmação antes da mesclagem. Então, você pode fazer:

git merge --squash testing

Isso irá mesclar, mas não confirmar. Então:

git diff
side2k
fonte
5

Parece que foi respondido aqui: https://public-inbox.org/git/[email protected]/

Da mesma forma, executando

$ git diff --cc $ M $ M ^ 1 $ M ^ 2 $ (base de mesclagem git $ M ^ 1 $ M ^ 2)

deve mostrar um patch combinado que explica o estado em US $ M em relação aos estados registrados em seus pais e na base de mesclagem.

max630
fonte
você sabe se alguma ferramenta pode ser configurada para exibir essa diferença lado a lado, potencialmente em poucas colunas (como na janela de resolução de conflitos de mesclagem do IntelliJ)? Sua resposta é exatamente o que eu estava procurando
Max
@ Max Não, eu tenho medo, não. A pesquisa no Google "diff visual n-way" fornece alguns links, então eu tentei.
max630 24/06
4

Eu acho que você só precisa de 'git show -c $ ref'. Tentar isso no repositório git em a8e4a59 mostra um diff combinado (mais / menos caracteres em uma das 2 colunas). Como o manual do git-show menciona, ele praticamente delega para o 'git diff-tree', para que essas opções pareçam úteis.

patthoyts
fonte
3
Não, para uma mesclagem "simples", git show -c $refmostra a mesma saída que citei, ou seja, sem diferenças. -cseleciona um modo diff combinado muito semelhante ao modo padrão para confirmações de mesclagem que é '--cc', consulte git help showe git help diff-tree. Ambos omitem completamente os arquivos que concordam com qualquer uma das versões pai desse arquivo.
Tilman Vogel
a8e4a59na verdade, não se enquadra na categoria de consolidação de mesclagem, quero dizer. Esse commit de mesclagem realmente contém um arquivo que difere de ambas as versões pai. Documentation/git-fast-import.txttem algumas coisas adicionadas de um pai e outras do outro. Isso resulta em saída não vazia de git diff-tree --cc. No entanto, apenas as alterações neste caso "conflitante" são mostradas. Todos os resultados de mesclagem "limpos", veja git show -m a8e4a59, não são mostrados.
Tilman Vogel
1
@ TilmanVogel: Obrigado por apontar que mesclagens de arquivos "desinteressantes" são deixadas de fora da git show -csaída. ( man git-diff-treeDiz "Além disso, ele lista apenas os arquivos que foram modificados a partir de todos os pais." Mas eu, pelo menos certamente não tinha visto isso.)
Paul Whittaker
3

no seu caso, você só precisa

git diff HEAD^ HEAD^2

ou apenas hash para você confirmar:

git diff 0e1329e55^ 0e1329e55^2
gurugray
fonte
4
Não, isso faz apenas uma diferença bidirecional entre os dois pais. O que eu estava pedindo era um modo que mostra simultaneamente a comparação entre o git merge-base HEAD^ HEAD^2e HEAD^e HEAD^2no mesmo estilo como é feito para arquivos que se fundiram com os conflitos.
Tilman Vogel
3

Se seu commit de mesclagem for 0e1329e5, como acima, você poderá obter o diff contido nessa mesclagem por:

git diff 0e1329e5^..0e1329e5

Eu espero que isso ajude!

hesham_EE
fonte
3

Se você está sentado no commit de mesclagem, isso mostra os diffs:

git diff HEAD~1..HEAD

Se você não estiver no commit de mesclagem, substitua HEAD pelo commit de mesclagem. Este método parece ser o mais simples e mais intuitivo.

Bruce Dawson
fonte
1
Esta não é uma saída "diff combinada". Obter diferenças entre cada par de pais e HEAD não é um problema aqui.
Tilman Vogel
2

Você pode usar o comando diff-tree com o sinalizador -c. Este comando mostra quais arquivos foram alterados na confirmação de mesclagem.

git diff-tree -c {merged_commit_sha}

Eu obtive a descrição da bandeira -c no Git-Scm :

Esse sinalizador altera a maneira como uma confirmação de mesclagem é exibida (o que significa que é útil apenas quando o comando recebe um, ou --stdin). Ele mostra as diferenças de cada um dos pais para o resultado da mesclagem simultaneamente, em vez de mostrar a diferença entre pares entre os pais e o resultado, um de cada vez (que é o que a opção -m faz). Além disso, lista apenas os arquivos que foram modificados por todos os pais.

Ehsan Mirsaeedi
fonte
2
Parece um bom artigo sobre este tópico: haacked.com/archive/2014/02/21/reviewing-merge-commits e talvez isso também: longair.net/blog/2009/04/16/git-fetch-and-merge
Devin G Rhode
1

Criei uma abordagem de uso geral para executar várias operações nos commits de mesclagem.

Etapa 1 : adicione um alias ao git editando ~/.gitconfig:

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

Etapa 2 : Em ~/.githelpers, defina uma função bash:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range $@"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range $@
}

Terceiro Passo : Lucro!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

Provavelmente há muito espaço para melhorias aqui, apenas juntei tudo para superar uma situação irritante. Sinta-se à vontade para zombar da minha sintaxe e / ou lógica do bash.

Nerdmaster
fonte
Observe que você pode alterar "..." para ".." no bit "awk", dependendo do que você precisa e do comando que está executando: stackoverflow.com/questions/462974/…
Nerdmaster