2012-06-12 23 views
30

Esiste un modo per visualizzare un'unione già impegnata in un diff di 3 vie?Visualizzazione fusione Git già impegnata in strumento differenziale a 3 vie esterno

Se un'enorme unione tra filiali è stata effettuata 3 settimane fa, c'è un modo per visualizzare un diff di 3 vie in uno strumento di diffusione esterno come BeyondCompare3? Sto cercando solo i file modificati nel commit unione. Bonus se potessi farlo visualizzare solo i conflitti e qualsiasi cosa cambiata manualmente, invece di vedere l'intera differenza di un file tra i due rami.

non mi dispiacerebbe accontentarsi di un diff 2 vie Se il lato sinistro aveva le ===== < < < < < >>>>> marcatori di conflitto e il lato destro è stato il risultato impegnato.

ho provato guardando diff-albero, diff-files, diff, difftool, mostrano, e gli altri e non poteva capirlo. So che Gitk mostrerà le modifiche solo nel commit di unione, ma non mi piace la vista di over-under diff ed è molto difficile capire quando ci sono tonnellate di cambiamenti.

Se solo potessi fare qualcosa di simile git difftool --cc firstparent..secondparent..result

risposta

2

non so come fare un diff tre vie in git senza qualche aggiustamenti, ma per un due vie diff userei meld. meld è in grado di fare una differenza a tre vie se controlli le tre diverse versioni del tuo progetto, fai una nuova diff per directory e seleziona l'opzione "Confronta a tre vie".

Per prima cosa installare fusione

sudo apt-get install meld

Quindi impostare fusione come difftool

git config --global diff.tool meld

Trova i commit

git log | more

Aprire i commit

git difftool <old-version>..HEAD

6

risposta Aggiornato: mia versione originale della sceneggiatura di sotto era viziato, nel senso che $conflicting_files in realtà non conteneva solo i file che realmente hanno avuto conflitti, ma tutti i file che sono stati modificati in entrambi i rami parentali (ma non necessariamente ha avuto conflitti). Inoltre, non utilizzava "lo strumento di unione configurato" come pubblicizzato nella logica, ma diffuse. Ho risolto entrambi i problemi nello current version of the script.

risposta originale: Diciamo che abbiamo un ramo "master" con lo sviluppo principale in corso, e un ramo "argomento" che aggiunge qualche caratteristica in cima a qualche stato (più vecchia) del maestro.Dicendo che stai cercando solo i file modificati nel commit di fusione presumo che tu sia interessato solo alle modifiche "topic" introdotte a "master" nel commit di unione (inclusa qualsiasi risoluzione di conflitto), non nel non- cambiamenti in conflitto che sono stati fatti in "master" poiché "topic" era ramificato. Inoltre supponendo che "master" è il primo genitore del merge commit e "tema" è il secondo, questo può essere realizzato con

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

Si noti che non ha senso utilizzare un 3-way diff qui stiamo osservando lo stato che include qualsiasi risoluzione di conflitto. Questo è anche ciò che GitHub sta mostrando per i commit di fusione, tra l'altro, vedi ad es. this merge commit che ho usato per i test.

per visualizzare solo i file in conflitto e le loro risoluzioni in uno strumento di diff 3 vie sono arrivato fino a questo 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 

sto usando Diffuse invece di Beyond Compare perché il primo può lavorare direttamente su Git impegna al contrario di file locali; cambia l'ordine degli argomenti a tuo piacimento. Per usare BC, probabilmente dovresti fare checkout temporanei; Stavo anche pensando di rifare l'unione, applicare la risoluzione conosciuta ed eseguire quello che è sempre configurato con git mergetool, ma entrambe queste idee richiederebbero più lavoro per non ingombrare l'albero di lavoro e per eseguire correttamente la pulizia.

+0

+1 per diffondere, potrebbe anche fare un diff in 4 modi con diversi commit – Johan

0

Come sschuberth, ho scritto una sceneggiatura che mi ha aiutato a trovare un cambiamento in un commit di unione. Funziona su un singolo file alla volta utilizzando vimdiff per mostrare le differenze tra i genitori e l'unione di commit.

#! /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) 

È un po 'hacky ma l'ho postato nel caso in cui aiuti qualcuno.

Problemi correlati