Suchen Sie einen Git-Zweig, der Änderungen an einer bestimmten Datei enthält

85

Ich habe 57 lokale Niederlassungen. Ich weiß, dass ich eine bestimmte Datei in einer von ihnen geändert habe, bin mir aber nicht sicher, welche. Gibt es einen Befehl, den ich ausführen kann, um herauszufinden, welche Zweige Änderungen an einer bestimmten Datei enthalten?

Dustin
quelle

Antworten:

87

Suchen Sie alle Zweige, die eine Änderung von FILENAME enthalten (auch vor dem (nicht aufgezeichneten) Verzweigungspunkt).

FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u

Manuell prüfen:

gitk --all --date-order -- $FILENAME

Alle Änderungen an FILENAME finden, die nicht mit master zusammengeführt wurden:

git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read x h; do if [ "`git log -n 1 --format=%H $h -- $FILENAME`" = "$h" ]; then echo $br; fi; done; done | sort -u
Seth Robertson
quelle
Muss ich in diesem Befehl etwas anderes als FILENAME ersetzen? Es werden alle 57 Filialnamen zurückgegeben.
Dustin
@Dustin: Wenn alle 57 Zweige diesen Dateinamen enthalten, enthalten alle 57 Zweige eine Änderung, die diesen Dateinamen enthält. Zweige beginnen mit der ältesten Revision, die für diesen Zweig erreichbar ist, auch wenn diese Revision vor dem Erstellen des Zweigs vorhanden war (der Zweig wird in gewisser Weise rückwirkend erstellt). Ich denke, Sie müssen Ihr Problem besser definieren. Wissen Sie, was die Änderung ist? Könnten Sie git log -Schange …oder verwenden git log --grep LOGMESSAGE …(wobei… den Rest des von mir erwähnten Befehls darstellt).
Seth Robertson
1
@Dustin: Eine andere Option ist die Verwendung, mit gitk --all -- filenameder Sie alle Änderungen an dieser Datei grafisch anzeigen können . Wenn Sie das betreffende Commit identifizieren können, können Sie anhand dessen feststellen, git branch --containsin welche Zweige das Commit migriert wurde. Wenn Sie sehen möchten, in welchem ​​Zweig das betreffende Commit ursprünglich erstellt wurde, dann googeln Sie git-what-branch. Beachten Sie jedoch, dass Zusammenführungen beim schnellen Vorlauf diese Informationen verdecken können.
Seth Robertson
@ Seth: Ich konnte mich nicht an die Commit-Nachricht oder die genaue Codeänderung erinnern. Ich habe nur eine allgemeine Idee. Das Problem ist, dass es noch nicht mit dem Master zusammengeführt wurde. Um gitk zu verwenden, müsste ich immer noch jeden Zweig auschecken, um zu finden, wonach ich suche. Es wäre schön, wenn ich sagen könnte: "git, zeig mir die Zweige, die seit ihrem Verzweigungspunkt Änderungen an FILENAME vorgenommen haben"
Dustin
1
Sie könnten die erste Zeile effizienter schreibengit log --all --format='--contains %H' "$file" | xargs git branch
Kojiro
49

Alles was Sie brauchen ist

git log --all -- path/to/file/filename

Wenn Sie die Branche sofort kennenlernen möchten, können Sie auch Folgendes verwenden:

git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}

Wenn Sie Umbenennungen hatten, möchten Sie diese möglicherweise --followfür den Git-Protokollbefehl einschließen .

Adam Dymitruk
quelle
14
Das zeigt die Commits, aber er fragte, welche Niederlassung. Fügen --sourceSie dort ein hinzu und Sie sind golden.
Karl Bielefeldt
Danke, aber ich denke nicht, dass alle Zweige für jedes Commit angezeigt werden. Aber es würde helfen.
Adam Dymitruk
1
Stimmt, aber in diesem speziellen Fall suchte er nur einen.
Karl Bielefeldt
Übrigens sollte der Pfad für asp.net in einem Format wie AppName / Controllers / XController.cs
Ali Karaca
8

Es sieht so aus, als wäre dies immer noch ein Problem ohne eine geeignete Lösung. Ich habe nicht genug Credits, um einen Kommentar abzugeben. Hier ist mein kleiner Beitrag.

Seth Robertsons erste Lösung funktionierte irgendwie für mich, gab mir aber nur lokale Zweige, unter denen sich viele falsch positive Ergebnisse befanden, wahrscheinlich aufgrund von Zusammenschlüssen aus dem stabilen Zweig.

Die zweite Lösung von Adam Dymitruk hat bei mir überhaupt nicht funktioniert. Was ist --format =% 5 für den Anfang? Es wird von git nicht erkannt, ich konnte nichts darüber finden und ich konnte es nicht dazu bringen, mit anderen Formatoptionen zu arbeiten.

Aber seine erste Lösung in Kombination mit der Option --source und einem einfachen grep erwies sich als hilfreich:

git log --all --source -- <filename> | grep -o "refs/.*" | sort -u

Dies gibt mir eine Reihe von Remote-Tags und -Zweigen sowie einen lokalen Zweig, in dem ich die letzten Änderungen an der Datei vorgenommen habe. Ich bin mir nicht sicher, wie vollständig dies ist.

UPDATE gemäß der Anfrage von @nealmcb, Sortieren der Zweige nach der letzten Änderung:

Zunächst können Sie den Grep in "refs / Heads /.*" ändern, wodurch nur die lokalen Zweige angezeigt werden. Wenn es nur wenige Zweige gibt, können Sie das letzte Commit jedes einzelnen wie folgt untersuchen:

git log -1 <branch> -- <filename>

Wenn es mehr Zweige gibt und Sie dies wirklich automatisieren möchten, können Sie die beiden Befehle mithilfe von xargs, Git-Protokollformatierung und einer anderen Sortierung in diesem Einzeiler kombinieren:

git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r

Dies führt zu einer Ausgabe wie folgt:

2020-05-07T15:10:59+02:00 refs/heads/branch1
2020-05-05T16:11:52+02:00 refs/heads/branch3
2020-03-27T11:45:48+00:00 refs/heads/branch2
Einfaltspinsel
quelle
Grosses Dankeschön. Wie wäre es nun mit dem Sortieren nach der letzten Änderung?
Nealmcb
0

Das Folgende ist eine unelegante Brute-Force-Methode, aber ich gehe davon aus, dass sie funktionieren sollte. Stellen Sie sicher, dass Sie alle nicht festgeschriebenen Änderungen zuerst gespeichert haben, da dadurch gewechselt wird, in welchem ​​Zweig Sie sich gerade befinden.

for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
    git checkout $branch && git grep SOMETHING
done
Whiteinge
quelle
1
Denn wenn Sie die Änderung kennen, können Sie verwendengit log -S
Seth Robertson
Welche Muschel nimmst du an? Bash?
Peter Mortensen
Keine Bashismen, die unter POSIX funktionieren sollten. Ich bin mir nicht sicher, ob for-each-refdiese shortFlagge trotzdem respektiert wird . Das heißt, ignoriere meine Antwort; Die anderen Antworten sind besser.
Whiteinge