2012-06-12 12 views
30

¿Hay alguna manera de ver una fusión que ya se ha confirmado en una diferencia de 3 vías?Ver la fusión de Git ya realizada en la herramienta diferencial externa de 3 vías

Si se cometió una enorme fusión entre ramas hace 3 semanas, ¿hay alguna manera de que pueda ver una diferencia de 3 vías en una herramienta de diferencia externa como BeyondCompare3? Estoy buscando solo los archivos cambiados en la combinación de fusión. Bonificación si pudiera obtenerlo solo para mostrarme los conflictos y cualquier cambio manual, en lugar de ver la diferencia completa de un archivo entre las dos ramas.

no me importaría conformarse con un diff de 2 vías si el lado izquierdo tenía los < < < < < ===== >>>>> marcas de conflicto y el lado derecho fue el resultado comprometida.

he intentado mirar diff-árbol, diff-archivos, diff, difftool, muestran, y otros, y no podían entenderlo. Sé que gitk mostrará los cambios solo en la fusión, pero no me gusta la vista de diff over-under y es muy difícil de entender cuando hay un montón de cambios.

Si tan sólo pudiera hacer algo como git difftool --cc firstparent..secondparent..result

Respuesta

2

No sé cómo hacer una diferenciación en tres sentidos en git sin algún hackery, pero para un diff de dos vías que haría uso de meld. meld es capaz de hacer un diff de tres vías si realiza el pago de las tres versiones diferentes de su proyecto, haga un nuevo diff por directorio y seleccione la opción "Three Way Compare".

Primero instale MELD

sudo apt-get install meld

A continuación, establezca MELD como el difftool

git config --global diff.tool meld

Encuentra las confirmaciones

git log | more

Abrir las confirmaciones

git difftool <old-version>..HEAD

6

respuesta Actualizado: Mi versión original de la escritura abajo era defectuoso en el sentido de que $conflicting_files, de hecho, no contenían sólo los archivos que realmente tenían conflictos, pero todos los archivos que se han cambiado en ambas ramas principales (pero no necesariamente tenía conflictos). Además, no estaba utilizando "la herramienta de combinación configurada" como se publicita en el análisis razonado, sino diffuse. He abordado ambos problemas en el current version of the script.

Respuesta original: Digamos que tenemos una rama "master" con el desarrollo principal pasando, y una rama "tema" que añade alguna característica en la parte superior de un estado (viejo) del maestro.Al decir que está buscando solo los archivos modificados en la confirmación de fusión, supongo que solo está interesado en los cambios "tema" introducido en "maestro" en la confirmación de fusión (incluida cualquier resolución de conflicto), no en el no- Los cambios conflictivos que se realizaron en "maestro" desde "tema" se ramificaron. Además suponiendo que "maestro" es el primer padre de la combinación de cometer y "tema" es la segunda, esto se puede lograr con

git difftool <merge commit>^1 <merge commit> 

Tenga en cuenta que no tiene sentido utilizar un 3 vías dif aquí como estamos viendo el estado que incluye cualquier resolución de conflicto. Esto también es lo que GitHub muestra para las asignaciones de fusión, por cierto, ver p. this merge commit que he usado para probar.

Para ver sólo los archivos en conflicto y sus resoluciones en una herramienta de diferencias de 3 vías se me ocurrió con este script

#!/bin/sh 

if [ $# -ne 1 ]; then 
    echo "Rationale : Show the conflict resolution of a given merge commit in the configured merge tool." 
    echo "Usage : $(basename $0) <merge commit>" 
    exit -1 
fi 

# Test e.g. with https://github.com/git/git/commit/8cde60210dd01f23d89d9eb8b6f08fb9ef3a11b8 
our=$1^1 
their=$1^2 
base=$(git merge-base $our $their) 

conflicting_files=$(git merge-tree $base $our $their | grep -A 3 "changed in both" | grep "base" | grep -Po "[^\s]+$") 
for f in $conflicting_files; do 
    diffuse -r $our -r $base -r $their $f 
done 

estoy usando Diffuse en lugar de Beyond Compare porque el primero puede trabajar directamente sobre confirmaciones Git a diferencia de los archivos locales; cambia el orden de los argumentos a tu gusto. Para usar BC, es probable que necesites hacer pagos temporales; También estaba pensando en rehacer la fusión, aplicar la resolución conocida y ejecutar lo que git mergetool está configurado, pero estas dos ideas requerirían más trabajo para no saturar su árbol de trabajo y hacer la limpieza correctamente.

+0

+1 para diffuse, incluso podría hacer una diferencia de 4 vías con diferentes commits – Johan

0

Al igual que sschuberth, escribí un script que me ayudó a encontrar un cambio en una fusión. Funciona en un único archivo a la vez utilizando vimdiff para mostrar las diferencias entre los padres y fusionar la confirmación.

#! /usr/bin/env ruby 

require 'pp' 
require 'tmpdir' 

merge = ARGV[0] || abort("I need a merge commit as the first argument") 
file = ARGV[1] || abort("I need a path as the second argument") 
cmd = "vimdiff" 

commits = `git log -n 1 #{merge} --format="%H %P"`.split(' ') 
abort "expected three commits" unless commits.size == 3 
commits[0], commits[1] = commits[1], commits[0] 
tmpdir = Dir.mktmpdir 
commits.each do |commit| 
    tfile = "#{tmpdir}/#{commit[0..10]}" 

    puts "git show #{commit}:./#{file} > #{tfile}" 
    `git show #{commit}:./#{file} > #{tfile}` 
    cmd += " #{tfile}" 
end 
puts cmd 
exec(cmd) 

Es un poco raro, pero lo publiqué por si ayuda a alguien.

Cuestiones relacionadas