Posso usare git diff su file non tracciati?


270

È possibile chiedere a git diff di includere file non tracciati nel suo output diff? O è la mia scommessa migliore per aggiungere i nuovi file che ho creato e i file esistenti che ho modificato e utilizzare

git diff --cached

?

Risposte:


267

Con le recenti versioni di git è possibile git add -Nil file (o --intent-to-add), che aggiunge un BLOB di lunghezza zero all'indice in quella posizione. Il risultato è che il tuo file "non tracciato" ora diventa una modifica per aggiungere tutto il contenuto a questo file di lunghezza zero e che appare nell'output "git diff".

git diff

echo "this is a new file" > new.txt
git diff

git add -N new.txt
git diff
diff --git a/new.txt b/new.txt
index e69de29..3b2aed8 100644
--- a/new.txt
+++ b/new.txt
@@ -0,0 +1 @@
+this is a new file

Purtroppo, come sottolineato, non puoi farlo git stashmentre hai un --intent-to-addfile in sospeso come questo. Anche se se hai bisogno di stash, aggiungi semplicemente i nuovi file e poi li stash. Oppure puoi usare la soluzione alternativa di emulazione:

git update-index --add --cacheinfo \
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt

(la creazione di un alias è il tuo amico qui).


Si scopre che la mia copia di Git non è abbastanza recente da aggiungere -N, ma questo risponde alla mia domanda.
Andrew Grimm,

1
Puoi emulare "git add -N new.txt" con "git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt" (come sono riuscito a mettere questo sulla risposta sbagliata?)
araqnid,


1
cosa succede se hai molti nuovi file, c'è un modo semplice per aggiungerli tutti e poi diff?
Vic

1
@Vicgit add -N .
Nathan,

92

Credo che tu possa differenziare i file nel tuo indice e i file non tracciati semplicemente fornendo il percorso di entrambi i file.

git diff --no-index tracked_file untracked_file

3
Funziona se hai più di un file non monitorato che hai creato dall'ultimo commit?
Andrew Grimm,

12
Sì, risposta perfetta! Posso quindi usare git diff --no-index untracked_file_1 untracked_file_2per ottenere la git diffcolorazione della sintassi ecc. Su diff ... bello.
Colin D Bennett,

40
Non capisco perché stai confrontando un file monitorato con un file non monitorato non correlato. Se si voleva solo per ottenere diff di output per il file non tracciata, si può semplicemente utilizzare /dev/nullinvece: git diff --no-index -- /dev/null <untracked_file>.

4
O semplicemente cat untracked_file_1, o forse printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"se hai davvero bisogno di un output ecologico. :) (Anche se su una nota più seria, tieni presente che la sostituzione dei comandi rimuoverà le nuove righe finali dal tuo file.)
Wildcard

8
Questa dovrebbe essere la risposta accettata - non richiede la modifica dell'indice di git; che, come dice l'autore originale, ha il suo rovescio della medaglia
DIMMSum

38

Per il mio gitting interattivo di tutti i giorni (in cui diffondo sempre l'albero di lavoro contro HEAD e vorrei avere file non tracciati inclusi nel diff), add -N/--intent-to-addè inutilizzabile, perché si rompe git stash .

Quindi ecco la mia git diffsostituzione. Non è una soluzione particolarmente pulita, ma dal momento che la uso solo in modo interattivo, sto bene con un trucco:

d() {
    if test "$#" = 0; then
        (
            git diff --color
            git ls-files --others --exclude-standard |
                while read -r i; do git diff --color -- /dev/null "$i"; done
        ) | `git config --get core.pager`
    else
        git diff "$@"
    fi
}

La digitazione dincluderà solo file non tracciati nel diff (che è ciò che mi interessa nel mio flusso di lavoro) e d args...si comporterà come un normale git diff.

Appunti:

  • Stiamo usando il fatto che in git diffrealtà sono solo i differenziali concatenati, quindi non è possibile distinguere l' doutput da un "vero diff", tranne per il fatto che tutti i file non tracciati vengono ordinati per ultimi.
  • L'unico problema con questa funzione è che l'output è colorato anche quando reindirizzato; ma non posso preoccuparmi di aggiungere la logica per quello.
  • Non sono riuscito a trovare alcun modo per includere i file non tracciati semplicemente assemblando un elenco di argomenti chiari per git diff. Se qualcuno scopre come fare questo, o se forse una funzione verrà aggiunta ad un gitcerto punto in futuro, si prega di lasciare una nota qui!

4
Ironia della sorte, la mia git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtsoluzione ho suggerito per Gits anziani fa lavoro con git stash, supponendo che hai già e69de29bb nel vostro db, ad esempio cercando di utilizzare add -Nin precedenza. Quindi a quanto pare non è esattamente equivalente a git add -Nin qualche modo: tbh non sono sicuro di come.
araqnid,

2
A testproposito, stai eseguendo un confronto delle stringhe anziché un controllo numerico dell'uguaglianza con il tuo comando. Non dovrebbe interessare nulla, ma test "$#" -eq 0è più precisamente ciò che è previsto.
Wildcard il

1
Sì, sembra ancora che tu debba farlo in modo accoppiato ... ma puoi falsificarlo in uno in lessmodo da non dover premere qper ogni file e sembra esattamente git diff, rimuovendo l'impaginazione per file ( -P), aggiungendolo successivamente ( | less), preservando color ( --color=always) e interpretandolo come color ( less -ro less -R). Quindi nel complesso è:do git -P diff --color=always -- /dev/null "$i"; done | less -r
iperpallium

Nel caso in cui desideri essere disturbato in futuro, test -t 1(ad es. if [ -t 1 ]; then color_arg=--color; fiO qualcosa del genere) è un modo per la shell di verificare se il suo output è un terminale, che è un modo utile per decidere sulla colorazione. E xargspotrebbe dare un modo per sbarazzarsi del ciclo while. Ne avrai ancora bisogno -n 1, quindi avvierà ancora git un sacco di volte, e dovrà comunque essere accoppiato in quel modo, ma ... se ne sbarazzerà whilee read, quindi forse è meglio?!? Lo lascio al lettore.
termina il

28

Non al 100% al punto, ma se per qualche motivo non vuoi aggiungere i tuoi file all'indice come suggerito dalla risposta accettata, ecco un'altra opzione:

Se i file non sono tracciati, ovviamente il diff è l'intero file, quindi puoi semplicemente visualizzarli con meno:

less $(git ls-files --others --exclude-standard)

Naviga tra loro con :ne :pper il prossimo e il precedente.

Aggiornamento dai commenti: se hai bisogno di un formato patch puoi anche combinarlo con git diff:

git ls-files --others --exclude-standard | xargs -n 1 git --no-pager diff /dev/null | less

Puoi anche reindirizzare l'output su un file o utilizzare un altro comando diff in questo caso.


6
puoi anche eseguire git diff /dev/null <untracked_tile>e ottenere la patch in formato patch anziché "solo" un file
SimSimY

2
questa risposta combinata con git diff è la soluzione perfetta.
iwind

22
git add -A
git diff HEAD

Genera patch se necessario, quindi:

git reset HEAD

Ciò ha il potenziale di perdere il lavoro precedente (pre), aggiungendo tutto. Soprattutto nel caso in cui uno si usi git add -pmolto spesso (che consiglio generalmente, a proposito) ... Questo dà un modo di fare le cose di base, solo ... va notato che ha il potenziale per il lato indesiderato effetti.
termina il

13

questo funziona per me:

git add my_file.txt
git diff --cached my_file.txt
git reset my_file.txt

L'ultimo passaggio è facoltativo, lascerà il file nello stato precedente (non tracciato)

utile se stai creando anche una patch:

  git diff --cached my_file.txt > my_file-patch.patch

La specificità di questa coppia add / reset è un bel contrasto con l'approccio del fucile da caccia di stackoverflow.com/a/50486906/313756 ... grazie per quello.
termina il

9

Le modifiche funzionano se messe in scena e non messe in scena con questo comando. I nuovi file funzionano quando messi in scena:

$ git diff HEAD

Se non vengono messi in scena, vedrai solo differenze di file.


26
HEADè il valore predefinito , quindi è lo stesso git diffche non risolve il problema.
Iulian Onofrei l'

4
Ciò richiede git addda ogni file non monitorato
SilvioQ

Se modifichi questa risposta per includerla git add, è la più semplice se il tuo caso d'uso è controllare cosa hai appena aggiunto / vuoi aggiungere
KCD

8

Per un file:

git diff --no-index /dev/null new_file

Per tutti i nuovi file:

for next in $( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null $next; done;

Come alias:

alias gdnew="for next in \$( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null \$next; done;"

Per tutti i file modificati e nuovi combinati come un solo comando:

{ git --no-pager diff; gdnew }

2

di solito quando lavoro con team di localizzazione remoti è importante per me avere una conoscenza preliminare del cambiamento fatto da altri team nello stesso file, prima di seguire git stages untrack -> messo in scena -> commit per quello ho scritto uno script bash che aiutami a evitare inutili risoluzioni di unione in conflitto con il team remoto o crea un nuovo ramo locale e confronta e unisci sul ramo principale

#set -x 
branchname=`git branch | grep -F '*' |  awk '{print $2}'`
echo $branchname
git fetch origin ${branchname}
for file in `git status | grep "modified" | awk "{print $2}" `
do
echo "PLEASE CHECK OUT GIT DIFF FOR "$file 
git difftool FETCH_HEAD $file ;
done

nello script sopra prendo il ramo principale remoto (non necessario il suo ramo principale) per FETCH_HEAD li faccio un elenco del mio file modificato e confronta i file modificati con git difftool

qui molti difftool supportati da git, configuro 'Meld Diff Viewer' per un buon confronto della GUI.


-9

Supponendo che non ci siano commit locali,

git diff origin/master

8
La domanda richiede un git diffcomando che include file non tracciati. Questo comando non li include. Inoltre, l'esistenza di commit locali non ha assolutamente nulla a che fare con la domanda.
toon81,

JFTR, I git merge --squash mybranch, e git diff mastermi ha mostrato le modifiche nei file non tracciati.
muammar,

2
È impossibile. Sembra che tu sia confuso sul significato di "non tracciato". Non tracciato non significa che un file sia tracciato in un ramo e non in un altro, significa che non è "in Git" da nessuna parte in alcun modo. Che tu schiaccia o meno non fa differenza. git diffnon mostra differenze nei file non tracciati: poiché sono non tracciati non ci sono mai differenze da mostrare, per definizione. È solo il modo in cui funziona Git. :)
toon81
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.