Czy mogę używać git diff na nieśledzonych plikach?

270

Czy można poprosić git diff o dołączenie nieśledzonych plików do wyjścia diff? A może najlepiej jest dodać nowe pliki, które utworzyłem, i istniejące pliki, które edytowałem i których używam

git diff --cached

?

Andrew Grimm
źródło

Odpowiedzi:

267

Dzięki najnowszym wersjom git możesz utworzyć git add -Nplik (lub --intent-to-add), który dodaje do indeksu w tym miejscu obiekt blob o zerowej długości. Wynikiem jest to, że plik „nieśledzony” staje się teraz modyfikacją dodającą całą zawartość do tego pliku o zerowej długości, co pojawia się na wyjściu „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

Niestety, jak wskazano, nie można, git stashdopóki --intent-to-addplik jest w toku. Chociaż jeśli chcesz ukryć, po prostu dodajesz nowe pliki, a następnie przechowujesz je. Lub możesz użyć obejścia emulacji:

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

(konfigurowanie aliasu jest tutaj Twoim przyjacielem).

araqnid
źródło
Okazuje się, że moja kopia Gita nie jest wystarczająco aktualna, aby dodać -N, ale to odpowiada na moje pytanie.
Andrew Grimm
1
Możesz emulować „git add -N new.txt” za pomocą „git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt” (jak udało mi się umieścić to na złą odpowiedź?)
araqnid
1
co jeśli masz dużo nowych plików, czy istnieje prosty sposób na dodanie ich wszystkich, a następnie na różnicę?
Vic
1
@Vicgit add -N .
Nathan
92

Sądzę, że możesz różnicować pliki w indeksie i pliki nieśledzone, podając po prostu ścieżkę do obu plików.

git diff --no-index tracked_file untracked_file
Harold
źródło
3
Czy to działa, jeśli masz więcej niż jeden nieśledzony plik, który utworzyłeś od ostatniego zatwierdzenia?
Andrew Grimm
12
Tak, idealna odpowiedź! Mogę wtedy użyć git diff --no-index untracked_file_1 untracked_file_2, aby uzyskać git diffkolorowanie składni itp na dyferencjału ... piękne.
Colin D Bennett
40
Nie rozumiem, dlaczego porównujesz plik śledzony z niepowiązanym plikiem nieśledzonym. Jeśli po prostu chciał dostać diff wyjście do pliku nieśledzonej, można po prostu użyć /dev/nullzamiast: git diff --no-index -- /dev/null <untracked_file>.
4
Lub po prostu cat untracked_file_1, a może printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"naprawdę potrzebujesz zielonej produkcji. :) (Chociaż bardziej poważnie, pamiętaj, że podstawienie polecenia usunie końcowe znaki nowego wiersza z pliku.)
Wildcard,
8
To powinna być zaakceptowana odpowiedź - nie wymaga zmiany indeksu gita; co, jak mówi oryginalny autor, ma swoją wadę
DIMMSum
38

Moje interaktywne codzienne gitowanie (gdzie cały czas różnicuję działające drzewo w stosunku do HEAD i chciałbym mieć w pliku diff nieuwzględnione pliki), add -N/--intent-to-addjest bezużyteczne, ponieważ pęka git stash .

Oto mój git diffzamiennik. To nie jest szczególnie czyste rozwiązanie, ale ponieważ naprawdę używam go tylko interaktywnie, jestem w porządku z hackiem:

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
}

Wpisywanie po prostu dbędzie zawierać niezrackowane pliki w diff (to jest to, na czym mi zależy w moim przepływie pracy) i d args...będzie się zachowywać jak normalne git diff.

Uwagi:

  • Używamy tutaj faktu, że git difftak naprawdę są to tylko poszczególne różnice skonkatenowane, więc nie jest możliwe dodróżnienie wyniku od „prawdziwego porównania” - z wyjątkiem faktu, że wszystkie nieśledzone pliki są sortowane na końcu.
  • Jedynym problemem związanym z tą funkcją jest to, że dane wyjściowe są pokolorowane, nawet po przekierowaniu; ale nie mogę zawracać sobie głowy dodaniem do tego logiki.
  • Nie mogłem znaleźć żadnego sposobu na włączenie nieśledzonych plików, po prostu tworząc zręczną listę argumentów git diff. Jeśli ktoś wymyśli, jak to zrobić, lub jeśli gitw przyszłości zostanie dodana funkcja , zostaw tutaj notatkę!
Jo Liss
źródło
4
Jak na ironię, moje git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtobejście, które zasugerowałem dla starszych gitów , działa git stash, zakładając, że masz już e69de29bb w db, np. Próbując użyć add -Nwcześniej. Najwyraźniej więc nie jest to git add -Nw jakiś sposób równoważne: nie jestem pewien, jak to zrobić.
araqnid
2
Nawiasem testmówiąc, wykonujesz porównanie ciągów zamiast numerycznej kontroli równości za pomocą polecenia. Nie powinno to wpływać na nic, ale test "$#" -eq 0dokładniej jest zgodne z przeznaczeniem.
Wildcard,
1
Tak, nadal wygląda na to, że musisz to zrobić parami ... ale możesz sfałszować go w jeden, lesswięc nie musisz naciskać qdla każdego pliku i wydaje się dokładnie tak git diff, usuwając paginację dla poszczególnych plików ( -P), dodając go później ( | less), zachowując kolor ( --color=always) i interpretując go jako kolor ( less -rlub less -R). Tak więc w sumie jest to:do git -P diff --color=always -- /dev/null "$i"; done | less -r
hyperpallium
Jeśli chcesz się martwić w przyszłości test -t 1(np. Czy if [ -t 1 ]; then color_arg=--color; ficoś w tym rodzaju), to sposób, w jaki powłoka sprawdza, czy jej wyjściem jest terminal, co jest przydatnym sposobem na wybór koloru. I xargsmoże dać sposób na pozbycie się pętli while. Nadal będziesz tego potrzebować -n 1, więc nadal będzie uruchamiał git kilka razy i nadal musi być w ten sposób parami, ale ... pozbywa się whilei read, więc może lepiej?!? Pozostawiam to czytelnikowi.
Lindes
28

Nie w 100% do rzeczy, ale jeśli z jakiegoś powodu nie chcesz dodawać plików do indeksu, jak sugeruje zaakceptowana odpowiedź, oto inna opcja:

Jeśli pliki nie są śledzone, oczywiście różnicą jest cały plik, więc możesz po prostu wyświetlić je z mniejszą liczbą:

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

Nawiguj między nimi za pomocą :ni, :paby przejść do następnego i poprzedniego

Aktualizacja z komentarzy: Jeśli potrzebujesz formatu łatki, możesz także połączyć go z git diff:

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

W tym przypadku możesz również przekierować dane wyjściowe do pliku lub użyć innego polecenia diff.

użytkownik1587520
źródło
6
możesz także uruchomić git diff /dev/null <untracked_tile>i pobrać łatkę w formacie łatki zamiast „tylko” pliku
SimSimY
2
ta odpowiedź w połączeniu z git diff jest idealnym rozwiązaniem.
iwind
22
git add -A
git diff HEAD

W razie potrzeby wygeneruj poprawkę, a następnie:

git reset HEAD
Amol Pujari
źródło
Może to spowodować utratę wcześniejszej (wstępnej) pracy przez dodanie wszystkiego. Zwłaszcza w przypadku, gdy ktoś korzysta z tego git add -pbardzo często (co zresztą ogólnie polecam) ... To daje sposób na zrobienie podstawowej rzeczy, po prostu ... należy zauważyć, że ma potencjał niepożądanej strony efekty.
Lindes
13

to działa dla mnie:

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

Ostatni krok jest opcjonalny, pozostawi plik w poprzednim stanie (bez śledzenia)

przydatne, jeśli tworzysz również łatkę:

  git diff --cached my_file.txt > my_file-patch.patch
Alejandro Moreno
źródło
Specyfika tej pary dodawania / resetowania stanowi niezły kontrast z podejściem shotgun z stackoverflow.com/a/50486906/313756 ... dzięki za to.
Lindes
9

Zmiany działają podczas przemieszczania i przemieszczania za pomocą tego polecenia. Nowe pliki działają podczas przemieszczania:

$ git diff HEAD

Jeśli nie są one ustawione, widoczne będą tylko różnice plików.

alairock
źródło
26
HEADjest wartością domyślną , więc jest to ta sama wartość , git diffktóra nie rozwiązuje problemu.
Iulian Onofrei,
4
Wymaga to git addod każdego
nieśledzonego
Jeśli edytujesz tę odpowiedź, aby uwzględnić git add, najprostszym jest, jeśli twoim przypadkiem użycia jest sprawdzenie, co właśnie dodałeś / chcesz dodać
KCD
8

Dla jednego pliku:

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

Dla wszystkich nowych plików:

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

Jako alias:

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

Dla wszystkich zmodyfikowanych i nowych plików połączonych jako jedno polecenie:

{ git --no-pager diff; gdnew }
radzimir
źródło
2

zwykle kiedy pracuję z zespołami zdalnymi, ważne jest dla mnie, aby mieć wcześniejszą wiedzę o zmianach dokonanych przez inne zespoły w tym samym pliku, zanim przejdę do etapów git bez śledzenia -> etapowe -> zatwierdzenie, napisałem skrypt bash, który pomóż mi uniknąć niepotrzebnego rozwiązania konfliktu scalania ze zdalnym zespołem lub załóż nowy oddział lokalny oraz porównaj i połącz w głównym oddziale

#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

w powyższym skrypcie pobieram zdalną gałąź główną (niekoniecznie jej gałąź główną) do FETCH_HEAD, robią one listę tylko mojego zmodyfikowanego pliku i porównują zmodyfikowane pliki do git difftool

tutaj wiele difftooli obsługiwanych przez git, konfiguruję Meld Diff Viewer dla dobrego porównania GUI.

adg
źródło
-9

Zakładając, że nie masz lokalnych zatwierdzeń,

git diff origin/master
Pradhan
źródło
8
Pytanie wymaga git diffpolecenia zawierającego nieśledzone pliki. To polecenie ich nie obejmuje. To, czy istnieją lokalne zatwierdzenia, nie ma absolutnie nic wspólnego z tym pytaniem.
toon81
JFTR, I git merge --squash mybranch, i git diff masterpokazałem mi zmiany w nieśledzonych plikach.
muammar
2
To niemożliwe. Wygląda na to, że jesteś zdezorientowany, co znaczy „nieśledzony”. Untracked nie oznacza, że ​​plik jest śledzony w jednej gałęzi, a nie w innej, oznacza to, że nie jest w żaden sposób „w Git”. To, czy zgniatasz, czy nie, nie ma znaczenia. git diffnie pokazuje różnic w nieśledzonych plikach: ponieważ nie są śledzone, z definicji nigdy nie ma żadnych różnic do pokazania. Tak działa Git. :)
toon81