Kann ich git diff für nicht verfolgte Dateien verwenden?

270

Ist es möglich, git diff zu bitten, nicht verfolgte Dateien in seine diff-Ausgabe aufzunehmen? Oder ist meine beste Wahl, um die neuen Dateien, die ich erstellt habe, und die vorhandenen Dateien, die ich bearbeitet habe, hinzuzufügen und zu verwenden

git diff --cached

?

Andrew Grimm
quelle

Antworten:

267

Bei neueren Git-Versionen können Sie git add -Ndie Datei (oder --intent-to-add) verwenden, die dem Index an dieser Stelle einen Blob mit der Länge Null hinzufügt. Das Ergebnis ist, dass Ihre "nicht verfolgte" Datei jetzt zu einer Modifikation wird, um den gesamten Inhalt zu dieser Datei mit der Länge Null hinzuzufügen. Dies wird in der Ausgabe "git diff" angezeigt.

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

Wie bereits erwähnt, können Sie dies leider nicht tun, git stashsolange eine --intent-to-addsolche Datei ansteht. Wenn Sie etwas verstauen müssen, fügen Sie einfach die neuen Dateien hinzu und verstauen sie dann. Oder Sie können die Emulationsumgehung verwenden:

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

(Das Einrichten eines Alias ​​ist dein Freund hier).

araqnid
quelle
Es stellt sich heraus, dass meine Kopie von Git nicht aktuell genug ist, um -N hinzuzufügen, aber dies beantwortet meine Frage.
Andrew Grimm
1
Sie können "git add -N new.txt" mit "git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt" emulieren (wie habe ich es geschafft, dies auf die falsche Antwort zu setzen?)
araqnid
1
Was ist, wenn Sie viele neue Dateien haben? Gibt es eine einfache Möglichkeit, alle hinzuzufügen und dann zu unterscheiden?
Vic
1
@ Vicgit add -N .
Nathan
92

Ich glaube, Sie können sich von Dateien in Ihrem Index und von nicht verfolgten Dateien unterscheiden, indem Sie einfach den Pfad zu beiden Dateien angeben.

git diff --no-index tracked_file untracked_file
Harold
quelle
3
Funktioniert das, wenn Sie mehr als eine nicht verfolgte Datei haben, die Sie seit dem letzten Commit erstellt haben?
Andrew Grimm
12
Ja, perfekte Antwort! Ich kann dann verwenden git diff --no-index untracked_file_1 untracked_file_2, um git diffSyntaxfarben usw. auf Diffs zu erhalten ... wunderschön.
Colin D Bennett
40
Ich verstehe nicht, warum Sie eine verfolgte Datei mit einer nicht verwandten nicht verfolgten Datei vergleichen. Wenn Sie nur eine Diff-Ausgabe für die nicht verfolgte Datei erhalten möchten, können Sie /dev/nullstattdessen einfach Folgendes verwenden : git diff --no-index -- /dev/null <untracked_file>.
4
Oder einfach cat untracked_file_1, oder vielleicht, printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"wenn Sie wirklich grünen Output brauchen. :) (Obwohl im Ernst, bitte beachten Sie, dass Befehlsersetzung die nachfolgenden Zeilenumbrüche aus Ihrer Datei entfernt.)
Wildcard
8
Dies sollte die akzeptierte Antwort sein - es ist nicht erforderlich, den Index von git zu ändern. was, wie der ursprüngliche Autor sagt, seinen Nachteil hat
DIMMSum
38

Für mein interaktives tägliches Gitting (bei dem ich den Arbeitsbaum ständig gegen den HEAD differenziere und nicht verfolgte Dateien im Diff haben möchte) add -N/--intent-to-addist es unbrauchbar, weil es kaputt geht git stash .

Also hier ist mein git diffErsatz. Es ist keine besonders saubere Lösung, aber da ich sie wirklich nur interaktiv benutze, bin ich mit einem Hack einverstanden:

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
}

Wenn Sie nur dtippen, werden nicht verfolgte Dateien in das Diff aufgenommen (was mir in meinem Workflow wichtig ist) und d args...es verhält sich wie normal git diff.

Anmerkungen:

  • Wir verwenden hier die Tatsache, dass git diffwirklich nur einzelne Unterschiede verkettet sind, so dass es nicht möglich ist, die dAusgabe von einem "echten Unterschied" zu unterscheiden - mit Ausnahme der Tatsache, dass alle nicht verfolgten Dateien zuletzt sortiert werden.
  • Das einzige Problem bei dieser Funktion ist, dass die Ausgabe auch bei Umleitung eingefärbt wird. aber ich kann mir nicht die Mühe machen, Logik dafür hinzuzufügen.
  • Ich konnte keine Möglichkeit finden, nicht verfolgte Dateien aufzunehmen, indem ich nur eine übersichtliche Argumentliste für zusammenstellte git diff. Wenn jemand herausfindet, wie das geht, oder wenn gitirgendwann in der Zukunft eine Funktion hinzugefügt wird, hinterlassen Sie bitte hier eine Notiz!
Jo Liss
quelle
4
Ironischerweise funktioniert meine git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtProblemumgehung, die ich für ältere Gits vorgeschlagen habe , mit git stash, vorausgesetzt, Sie haben bereits e69de29bb in Ihrer Datenbank, z. B. indem Sie versuchen, es add -Nzuvor zu verwenden . Anscheinend ist es git add -Nin gewisser Weise nicht genau gleichbedeutend mit : Ich bin mir nicht sicher, wie.
Araqnid
2
Übrigens führen Sie mit Ihrem testBefehl eher einen Zeichenfolgenvergleich als eine numerische Gleichheitsprüfung durch. Sollte nichts beeinflussen, test "$#" -eq 0ist aber genauer, was beabsichtigt ist.
Wildcard
1
Ja, es sieht immer noch so aus, als müssten Sie es paarweise tun ... aber Sie können es in eine fälschen, lesssodass Sie nicht qfür jede Datei drücken müssen, und es fühlt sich genau so an, als würden Sie die git diffPaginierung pro Datei ( -P) entfernen und sie anschließend wieder hinzufügen ( | less), Farbe beibehalten ( --color=always) und als Farbe ( less -roder less -R) interpretieren . Insgesamt ist es also:do git -P diff --color=always -- /dev/null "$i"; done | less -r
Hyperpallium
Für den Fall, dass Sie in Zukunft gestört werden möchten test -t 1(z. B. if [ -t 1 ]; then color_arg=--color; fioder so), kann die Shell auf diese Weise überprüfen, ob es sich bei der Ausgabe um ein Terminal handelt. Dies ist eine nützliche Methode, um über die Farbgebung zu entscheiden. Und xargskönnte einen Weg geben, um die while-Schleife loszuwerden. Du wirst das immer noch brauchen -n 1, also wird es immer noch ein paar Mal gestartet und muss immer noch paarweise so sein, aber ... es wird los whileund readvielleicht ist das besser?!? Das überlasse ich dem Leser.
Lindes
28

Nicht 100% auf den Punkt, aber wenn Sie aus irgendeinem Grund Ihre Dateien nicht zum Index hinzufügen möchten, wie in der akzeptierten Antwort vorgeschlagen, ist hier eine andere Option:

Wenn die Dateien nicht verfolgt werden, ist der Unterschied offensichtlich die gesamte Datei, sodass Sie sie nur mit weniger anzeigen können:

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

Navigieren Sie zwischen ihnen mit :nund :pfür das nächste und vorherige.

Update aus den Kommentaren: Wenn Sie ein Patch-Format benötigen, können Sie es auch kombinieren mit git diff:

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

Sie können die Ausgabe auch in eine Datei umleiten oder in diesem Fall einen anderen diff-Befehl verwenden.

user1587520
quelle
6
Sie können git diff /dev/null <untracked_tile>den Patch auch im Patch-Format ausführen und
abrufen,
2
Diese Antwort in Kombination mit Git Diff ist die perfekte Lösung.
Wind
22
git add -A
git diff HEAD

Generieren Sie bei Bedarf einen Patch und dann:

git reset HEAD
Amol Pujari
quelle
Dies hat das Potenzial, frühere (Vor-) Arbeiten zu verlieren, indem alles hinzugefügt wird. Besonders dann, wenn man git add -psehr oft Gebrauch macht (was ich übrigens generell empfehle) ... Dies gibt eine Möglichkeit, das Grundlegende zu tun, es sollte nur ... beachtet werden, dass es das Potenzial für unerwünschte Seiten hat Auswirkungen.
Lindes
13

das funktioniert bei mir:

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

Der letzte Schritt ist optional. Die Datei bleibt im vorherigen Status (nicht verfolgt).

nützlich, wenn Sie auch einen Patch erstellen:

  git diff --cached my_file.txt > my_file-patch.patch
Alejandro Moreno
quelle
Die Spezifität dieses Add / Reset-Paares ist ein schöner Kontrast zum Shotgun-Ansatz von stackoverflow.com/a/50486906/313756 ... danke dafür.
Lindes
9

Änderungen funktionieren, wenn sie mit diesem Befehl bereitgestellt und nicht bereitgestellt werden. Neue Dateien funktionieren beim Bereitstellen:

$ git diff HEAD

Wenn sie nicht bereitgestellt werden, werden nur Dateiunterschiede angezeigt.

Alairock
quelle
26
HEADist der Standardwert , daher ist dies derselbe git diff, der das Problem nicht löst.
Iulian Onofrei
4
Dies erfordert git addvon jeder nicht verfolgten Datei
SilvioQ
Wenn Sie diese Antwort so bearbeiten, dass git addsie die Antwort enthält , ist es am einfachsten, wenn Ihr Anwendungsfall darin besteht, zu überprüfen, was Sie gerade hinzugefügt haben / hinzufügen möchten
KCD
8

Für eine Datei:

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

Für alle neuen Dateien:

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

Als Alias:

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

Für alle geänderten und neuen Dateien, die als ein Befehl zusammengefasst sind:

{ git --no-pager diff; gdnew }
Radzimir
quelle
2

Wenn ich mit Remote-Location-Teams zusammenarbeite, ist es für mich normalerweise wichtig, dass ich vorher weiß, welche Änderungen von anderen Teams in derselben Datei vorgenommen wurden, bevor ich den Git-Phasen folge, die nicht verfolgt -> inszeniert -> festgeschrieben wurden Helfen Sie mir, unnötige Probleme beim Zusammenführen von Konflikten mit dem Remote-Team zu vermeiden, oder erstellen Sie einen neuen lokalen Zweig und vergleichen und führen Sie den Hauptzweig zusammen

#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

Im obigen Skript hole ich den Remote-Hauptzweig (nicht unbedingt den Hauptzweig) nach FETCH_HEAD. Sie erstellen nur eine Liste meiner geänderten Dateien und vergleichen die geänderten Dateien mit git difftool

Hier viele Difftools, die von Git unterstützt werden. Ich konfiguriere 'Meld Diff Viewer' für einen guten GUI-Vergleich.

adg
quelle
-9

Angenommen, Sie haben keine lokalen Commits.

git diff origin/master
Pradhan
quelle
8
In der Frage wird nach einem git diffBefehl gefragt , der nicht verfolgte Dateien enthält. Dieser Befehl enthält sie nicht. Ob lokale Commits existieren oder nicht, hat absolut nichts mit der Frage zu tun.
Toon81
JFTR, ich git merge --squash mybranchund git diff masterzeigte mir die Änderungen in nicht verfolgten Dateien.
Muammar
2
Das ist nicht möglich. Sie scheinen verwirrt darüber zu sein, was "nicht verfolgt" bedeutet. Untracked bedeutet nicht, dass eine Datei in einem Zweig und nicht in einem anderen verfolgt wird, sondern dass sie in keiner Weise "in Git" ist. Ob Sie quetschen oder nicht, spielt keine Rolle. git diffzeigt keine Unterschiede in nicht verfolgten Dateien: Da sie nicht verfolgt werden, gibt es per Definition keine Unterschiede zu zeigen. So funktioniert Git. :)
toon81