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.


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.


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

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

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

5

Parece que foi respondido aqui: https://public-inbox.org/git/7vd392ezhx.fsf@alter.siamese.dyndns.org/

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.


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.


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

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!


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.


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.



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.


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
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.