Ich denke, die Antwort auf diese Frage ist, dass git nicht dafür gemacht wurde. Git mag die Idee von "Kindern eines Commits" nicht wirklich, und dafür gibt es einen sehr guten Grund: Es ist nicht sehr gut definiert. Da ein Commit nichts über seine Kinder weiß, ist es ein sehr vages Set. Möglicherweise haben Sie nicht alle Zweige in Ihrem Repo und daher fehlen einige Kinder.
Gits interne Speicherstruktur macht auch die Suche nach den Kindern einer Commit eine ziemlich teure Operation, wie Sie die Revision Grafik aller Köpfe zu ihren entsprechenden Wurzeln gehen oder bis Sie alle Commits gesehen, deren Kinder Sie wissen möchten Über.
Das einzige Konzept dieser Art, das Git unterstützt, ist die Idee von einem Commit mit anderen Commit. Aber diese Funktion wird nur von sehr wenigen Git-Befehlen unterstützt (git branch
ist eine davon). Und wo git es unterstützt, unterstützt es es nicht für willkürliche Commits, sondern nur für Branch Heads.
Dies alles mag eine ziemlich harte Einschränkung von Git erscheinen, aber in der Praxis stellt sich heraus, dass Sie die "Kinder" eines Commits nicht benötigen, aber normalerweise nur wissen müssen, welche Zweige ein bestimmtes Commit enthalten.
Das alles gesagt: Wenn Sie wirklich die Antwort auf Ihre Frage erhalten möchten, müssen Sie Ihr eigenes Skript schreiben, das es findet. Der einfachste Weg ist, mit der Ausgabe von git rev-list --parents --reverse --all
zu beginnen. Wenn Sie diese Zeile für Zeile analysieren, erstellen Sie einen Baum und markieren für jeden Knoten, ob es sich um ein untergeordnetes Element der gesuchten Commits handelt. Sie tun dies, indem Sie die Commits selbst markieren, sobald Sie sie erfüllen, und dann diese Eigenschaft an alle ihre Kinder weiterleiten und so weiter.
Sobald Sie einen Commit haben, der mit allen Commits markiert ist, fügen Sie ihn Ihrer "Lösungsliste" hinzu und markieren alle seine untergeordneten Elemente als tot - sie dürfen keine ersten Commits mehr enthalten. Diese Eigenschaft wird dann auch an alle ihre Nachkommen weitergegeben.
Sie können hier ein wenig Speicher speichern, wenn Sie keine Teile des Baums speichern, die keine der von Ihnen angeforderten Commits enthalten.
bearbeiten Hacked einigen Python-Code
#!/usr/bin/python -O
import os
import sys
if len(sys.argv) < 2:
print ("USAGE: {0} <list-of-revs>".format([sys.argv[0]]))
exit(1)
rev_list = os.popen('git rev-list --parents --reverse --all')
looking_for = os.popen('git rev-parse {0}'
.format(" ".join(sys.argv[1:]))).read().splitlines()
solutions = set()
commits = {}
for line in rev_list:
line = line.strip().split(" ")
commit = set()
sha = line[0]
for parent in line[1:]:
if not parent in commits:
continue
commit.update(commits[parent])
if parent in solutions:
commit.add("dead")
if sha in looking_for:
commit.add(sha)
if not "dead" in commit and commit.issuperset(looking_for):
solutions.add(sha)
# only keep commit if it's a child of looking_for
if len(commit) > 0:
commits[sha] = commit
print "\n".join(solutions)
ich nicht von einem einfachen (effizient) Weg, dies zu tun denken kann, kurz eine Liste aller zu erzeugen verschmelzen verpflichtet, und Testen jeden einer einzeln, um zu sehen, ob jedes der fraglichen Commits von dort erreichbar ist. Könnte relativ einfach geschrieben werden, aber es wäre * langsam *. Ich denke, dass eine neuere (d. H. 1.8+) Version von 'git' an einigen Stellen eine Option' --contains' hinzugefügt hat, die das Ganze ein wenig leichter machen könnte. – twalberg
Gehören b und c zu verschiedenen Zweigen? – ShadyKiller
@ShadyKiller: Im konkreten Beispiel ja; im Allgemeinen, nein. Alle drei können sich in demselben Zweig befinden (in diesem Fall wäre die Antwort nur das, was am nächsten kommt) oder verschiedene Zweige. Zum Teufel, es kann mehr oder weniger als drei Commits geben; das war eine relativ willkürliche Zahl. –