/ / git diff rinominato / spostato e modificato i file, ma salta rinominato / spostato e file identici - git, rinomina, sposta, git-diff, combina

git diff rinominato / spostato e modificato i file, ma salta rinominato / spostato e file identici - git, rinomina, sposta, git-diff, combina

Sto usando:

git diff HEAD --diff-filter=R -M

con lo strumento diff esterno di fusione per mostrare i fileche sono stati entrambi rinominati / spostati e modificati. Faccio sempre un git diff prima di fare un commit per controllare il mio lavoro e per assemblare correttamente il messaggio di commit. Spesso cambierò il nome / spostamento dei file, il che richiederà anche alcune modifiche al percorso all'interno dei file che fanno riferimento a file rinominati / spostati.

Il mio problema è che per mostrare il diff di afile che è stato rinominato e quindi modificato, git diff apre anche una serie di finestre di fusione per i file che sono stati rinominati, ma non modificati. Questo può essere molto fastidioso. Come ottenere git diff per saltare i file rinominati ma non modificati? Vedrò tutti i file elencati come rinominati / spostati quando digito git status in un modo molto più pulito, quindi non voglio i popup per i file identici con git diff.

risposte:

1 per risposta № 1

Sto avendo lo stesso problema e ho trovato un alias che ha fatto il trucco (sto usando git 2.8.3)

[alias]
difftoolr = "!git difftool "$@" -- .  $((git diff "$1" -M100% --diff-filter=R --name-only & git diff "$1" -M100% --diff-filter=R --name-only -R) | sed "s/\(.*\)/:(exclude)\1/g") #"

Come usare:

difftoolr commit1..commit2 -M

(vedi in fondo per altri esempi)

Come funziona:

Immagina di avere tre file che sono statirinominato. Uno di questi ha il suo contenuto effettivamente cambiato (quindi lo vuoi esaminare usando il tuo difftool) ma gli altri due sono identici tranne per il percorso o il nome (e vuoi ignorarli).

(different) path/file.old  -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new

Ciò che l'alias fa è generare specifiche di percorso che escludono esplicitamente fileB e fileC, cioè quei file che nonostante la ridenominazione mantengono inalterato il contenuto.
In altre parole stiamo generando questi filespec:

-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new

Si noti la parte (forse più difficile): il vecchio percorso del file e il nuovo percorso del file devono essere entrambi esplicitamente escluso.

Per fare ciò, emettiamo a git diff con le seguenti direttive:

  • -M100%: segui i nomi. Il che significa che git sta supponendo che sia stato effettuato un rinominazione e terremo conto di queste informazioni per fare confronti a coppie. La soglia è 100%, che indica a git di considerare i file rinominati che hanno esattamente lo stesso contenuto, ma non quelli che sono stati modificati.
  • --diff-filter=R: elenca solo i file che git considera rinominati, omette gli altri.
  • --names-only: basta emettere i nomi dei file, nessun'altra informazione
  • -R: Al contrario. In un pezzo della sceneggiatura scambiamo l'ordine di paragone (una sorta di commutazione dei lati sinistro e destro), quindi produrrà anche i vecchi nomi di file. Ad esempio il -R direttiva elenca il file newPath/fileB.new come path/fileB.old.
  • ...sed...: e infine aggiungiamo la direttiva sull'esclusione :(exclude) all'inizio di tutti i nomi di file.

Per affrontare altri casi ho creato tre diversi alias (non proprio eleganti, mi piacerebbe qualcosa di più flessibile) in modo che possa essere usato per specificare i diversi tipi di confronto.

git difftoolr0 -M
git difftoolr1 HEAD~1..HEAD -M
git difftoolr2 HEAD --cached -M

In tutti i casi i "lati dei confronti" (commit, --cached o qualunque) devono essere specificati come primo parametro (i). Per esempio git difftoolr2 -M HEAD --cached non ha funzionato (perché -M viene prima).

[alias]
# takes no parameter: sample usage:  git difftoolr0  -M
difftoolr0 = "!git difftool "$@" -- .  $((git diff -M100% --diff-filter=R --name-only & git diff -M100% --diff-filter=R --name-only -R) | sed "s/\(.*\)/:(exclude)\1/g") #"

# takes 1 parameter in first position: sample usage:  git difftoolr1 HEAD~1..HEAD -M
difftoolr1 = "!git difftool "$@" -- .  $((git diff "$1" -M100% --diff-filter=R --name-only & git diff "$1" -M100% --diff-filter=R --name-only -R) | sed "s/\(.*\)/:(exclude)\1/g") #"

# takes 2 parameters in first positions: sample usage:  git difftoolr2 HEAD --cached  -M
difftoolr2 = "!git difftool "$@" -- .  $((git diff "$1" "$2" -M100% --diff-filter=R --name-only & git diff "$1" "$2" -M100% --diff-filter=R --name-only -R) | sed "s/\(.*\)/:(exclude)\1/g") #"

Infine, BeyondCompare può soddisfare anche le tue esigenze (e le mie).
Permette facilmente di alternare la differenza side-by-side in un diff "non strutturato".

Quest'ultimo toglie le cartelle e lascia solo i nomi. Se il nome file è lo stesso (ma i percorsi possono essere diversi) vengono considerate due versioni dello stesso file (ad esempio path/file.png e newPath/file.png). In questo caso, se il contenuto non è cambiato, possono essere omessi facilmente utilizzando un pulsante sulla barra superiore.

Nel caso si verifichino conflitti di "naming" (diversi filesullo stesso lato del confronto hanno lo stesso nome, sotto percorsi diversi), ne sceglierà solo uno per il confronto, e ignora gli altri.