Finden Sie die merge-base zwischen einem remote-und einem commit
Gegeben, eine Fernbedienung und ein commitish, ich will es zu verschmelzen in einen Ziel-branch auf origin und generiert ein "diff" für Sie.
Wenn der Ziel-branch existiert, Ursprung, es ist ein einfacher Aufruf merge-base
um zu überprüfen, ob die remote-commitish ist in Bezug auf Herkunft Baum und ein diff vom merge-base, um die remote-commit.
Wenn es nicht vorhanden ist, blind Erstellung der neuen Niederlassung riskant sein kann, wie ich will, um sicherzustellen, dass die Geschichte gebracht wird, ist in Bezug auf die Herkunft.
Gerade jetzt, ich bin mit rev-list
zu bestimmen, wenn die commit hat eine gemeinsame Geschichte mit origin. Insbesondere bin ich mit git rev-list --max-parents=0 --remotes=origin
und git rev-list --max-parents=0 committish
um die root-commit(s) für die Herkunft und die remote-commit und überprüfen, dass Sie mindestens eine gemeinsame Wurzel (rev-list
erzeugen kann, die die union oder die Differenz zwischen commits/Fernbedienungen aber nicht die Kreuzung scheint es).
Jetzt weiß ich, dass die remote-commit ist verwandt, aber ich muss noch generiert ein "diff". Gerade jetzt, ich nur wissen, was root commits im Ursprung erreichbar sind die neuen commit. Wie finde ich die besten merge-base in origin, wenn ich nicht weiß, in welcher Branche ist sehr eng mit dem verpflichten will ich bringen? Werde ich über das komplett falsch?
In anderen Worten, die Herkunft und commitish, wie identifiziere ich den merge-base-X gegeben keine Kenntnisse über die Hierarchie von origin? git merge-base origin committish
ist nicht gültig, da die Herkunft nicht angeben, die ein einzelner Begehen.
o----o----o master \
\ }-- everything reachable from origin
o---X---o branch2 /
\
o---o----o---o----o---o commitish }-- new data from remote
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, das denke ich. Lass uns Zurückspulen und überprüfen. Ich bin sicher, Sie haben gesehen, wie einige, aber es sind viele Erklärungen für diese sind ... nicht so gut. (Auch, Sie habe mit der überarbeitung Ihrer Frage habe ich beantwortet, so dass wir vielleicht über ein paar Drähte...)
Fernbedienungen, remote-tracking branches
gitrevisions
, undgit rev-list
Einen remote wie
origin
ist nur ein name. "Ein name für das, was" ist eine gute Frage (nicht von dir, zumindest nicht direkt, aber man Sie Fragen sollte). Die wichtigsten "für was" ist einfach genug: für eine URL. Der nameorigin
speichert eine URL wiessh://[email protected]/path/to/repo
. Es ist normalerweise eine URL an jeder Fernbedienung. (Sie können eine zweite, andere zu schieben, wenn Sie möchten. Es gibt einige selten-Fällen nützlich, wo Sie können mehr als eine push-URL. Aber meistens ist es nur ein kurzer name, der für eine URL.) Die wichtige Sache zu erinnern ist hier nicht nur, dass es ein name, eine URL, aber auch, dass es ist ein weiteres Git am anderen Ende der URL. Das andere Git-repository hat seine eigenen branch-und tag-Namen.Einem remote-name wie
origin
ist nicht einen Zweig oder ein tag. Von selbst, es identifiziert nicht verpflichtet. Die Dinge, die tun identifizieren von übertragungen von Namen sind, Ihre eigenen (lokalen) Zweig, Namen wiemaster
; keine tag-Namen, die Sie haben, wiev1.3
wenn Sie so ein tag; und remote-tracking-branch-Namen wieorigin/master
. Jede dieser name identifiziert eine bestimmte commit -. Im Falle eines remote-tracking-branch-Namen wieorigin/master
es identifiziert die commit Git sah, das Letzte mal Git-Kontakt zu den anderen Git über die URL. In anderen Worten, remote-tracking branches erinnern, was Ihr Git sah das Letzte mal gesprochen haben, dass andere Git. Sie sind nur als up-to-date, wie Ihr dem Git die aktuellste vollständige Gespräch. (Git-tun Sie partielle updates auf erfolgreichegit push
Operationen, aber es werden nur vollständige updates aufgit fetch
Operationen, wo Sie nicht beschränkt, die zu Holen. Wenn Siegit pull
bedeutet es einen eingeschränktenfetch
, die Blätter zumindest einige Ihrer remote-tracking branches out-of-date.)Etwas verwirrend, jedoch, wie dokumentiert in
gitrevisions
, die Auflösung Weg für ein unqualifizierter name X ist:.git/X
vorhanden ist; wenn ja, verwenden Sie diese. (Dies stellt sicher, dassHEAD
bedeutet immer den KOPF zu Begehen. Als Nebeneffekt, es bedeutet, Sie sollten nicht Namen eine FilialeMERGE_HEAD
,ORIG_HEAD
,CHERRY_PICK_HEAD
oderFETCH_HEAD
, da sich die verschiedenen Git-Operationen lassen sich Dateien mit diesem Namen hinter sich.)refs/X
vorhanden ist; wenn ja, verwenden Sie diese.refs/tags/X
vorhanden ist; wenn ja, verwenden Sie diese.refs/heads/X
vorhanden ist; wenn ja, verwenden Sie diese.refs/remotes/X
vorhanden ist; wenn ja, verwenden Sie diese.refs/remotes/X/HEAD
existiert; wenn ja, verwenden Sie diese.Dieser letzten ein—item-6—bedeutet, dass mithilfe der remote-name
origin
von selbst, wenn es einerefs/remotes/origin/HEAD
versuchen ... und Git jetzt setzt normalerweise einerefs/remotes/origin/HEAD
indirekten Verweis, der auf die Referenz-Git wählen, wenn Sie hat Ihre ursprünglichegit clone
.1 Dies ist in der Regelrefs/remotes/origin/master
so dassorigin
von selbst kann, aber nicht unbedingt hat, "meine"origin/master
, die ist ein remote-tracking-branch name.Mittlerweile
git rev-list
hat seine eigene spezielle flags, einschließlich--remotes
. Diese zu verstehen, alle Ihre volle Git Herrlichkeit, möchten Sie vielleicht zu finden als auch zugit for-each-ref
, aber Sie beziehen sich auf die gleiche Suche wir oben gesehen mitgitrevisisons
, und die Idee, dass der name der Referenz-Raum ist hierarchisch.Alle remote-tracking branches für
origin
Leben inrefs/remotes/origin/
. Das macht es leicht für uns, Sie alle zu finden. Und in der Tat, Sie sind konstruiert, indem die anderen Git-Filialen—diejenigen, die die lokalen Niederlassungen des Git am anderen Ende der URL, die im Zusammenhang mit der remote—und einfach umbenennen Sie. Beim ausführengit fetch origin
, so dass Sie Ihre Git hat das ganze Gespräch mit den anderen Git, Git es wird eine Liste aller Ihrer Zweige, plus die spezifischen commit-IDs, mit denen die Zweige. Dann Git änderungen Ihrerrefs/heads/X
zu Ihremrefs/remotes/origin/X
so dass Sie aktualisieren Sie Ihre remote-tracking branches.(Add
--prune
um Ihre eigenen Git zu löschen alle Links über remote-tracking-branches, die du hast, dass nicht mehr über einen entsprechenden regulären Zweig im anderen Git-repository. Sonst können Sie noch ein paar Geister hinter sich gelassen. Können Sie ignorieren die spezielle "remote-HEAD" ganz da es sich um eine indirekte Referenz, d.h., es enthält lediglich den Namen von einem anderen remote-tracking-branch.)1einer Sehr alten Version von Git nicht tun, und einige ältere Versionen kann es nicht 100% korrekt, sondern nur erraten. Neuere Gits, können die indirekten Zweig jedes mal korrekt. Aus irgendeinem Grund, obwohl, es ist nur auf den ersten Klon. Wenn Sie es ändern möchten, können Sie jederzeit verwenden
git remote set-head
, und Sie können es so einrichten, zeigen Sie auf alle Ihre remote-tracking-branches, unabhängig davon, was auf der anderen Git.Namen verweisen auf commits und Eigenschaften von (lokalen) Markenbezeichnungen
Oben, ich habe erwähnt, dass diese verschiedenen Namen zeigen Sie auf eine bestimmte commit -. Dies ist in der Tat wahr von alle Namen im Git. Die Sache, die macht, Branchen Besondere, unterscheiden sich von den tags zum Beispiel, dass Markenbezeichnungen sind voraussichtlich im Laufe der Zeit ändern, normalerweise in einer "add new commits," - Manier.
Es verpflichtet sich, die zeigen, nach hinten, zu anderen (früheren /Vorfahren) verpflichtet. Als eine wichtige Nebenwirkung oder Wirkung, dies bedeutet, dass die verpflichtet sind in der Regel auf viele Zweige, und dass zwei verschiedene Namen, die möglicherweise auf die gleichen Begehen.
Es ist eine andere Sache, die eine Menge Fragen hier, und das ist, dass eine lokale Niederlassung name kann eine (und nur eine) upstream Einstellung. Wenn eine upstream -, es besteht aus zwei teilen: der name des entfernten, und den Namen einer Filiale gesehen, die remote (d.h., "Rückgängigmachen" der remote-tracking-branch-mapping). Diese upstream-Einstellung teilt Git mit, was Sie möchten, zu fusionieren oder rebase auf, wenn Sie merge oder rebase. Durch die Ausführung der Verzweigung durch die remote-tracking-mapping (ersetzt
master
mitorigin/master
), Git kann Ihnen auch sagen, wie weit Sie vor und/oder hinter dir, der die remote-tracking-branch.(Natürlich, Sie haben zu laufen
git fetch
zu update alle remote-tracking-branches, bevor das Letzte bit ist nützlich.)Nun, ich denke, wir können zurück zu Ihrer Frage...
Was Begehen wird, die Sie Zusammenführen, mit?
Ich denke, was Sie hier sagen, ist, dass manchmal, Sie haben einfach nicht genug Informationen.
Wenn Sie eine branch name, können Sie den Ziel-branch auf origin:
Dies sagt uns, die gleiche Sache wie:
mit dem offensichtlichen Unterschied, dass der erstere nicht abgebildet durch, um die entsprechenden remote-tracking-branch, während die letzteren ist.
Wenn Sie nicht gegeben sind, eine branch name, aber es gibt keine Möglichkeit zu sagen, was der Benutzer will, zu verschmelzen mit—es sei denn, natürlich, Sie nehmen zusätzliche Argumente.
Dies ist in der Tat, wie
git merge
selbst funktioniert:Den merge-base von entweder Zusammenführen, wird die commit(s) gefunden
git merge-base
wie laufen auf beidenHEAD
(die aktuelle commit-definition) und1234567
oderHEAD@{u}
(das Ziel verpflichten, oder der Standardwert ist der aktuelle branch im upstream).Bearbeiten hinzufügen Hinweis: Durch die Art und Weise,
HEAD
ist immer die aktuelle Begehen. Es ist auch in der Regel den aktuellen branch-Namen, weilHEAD
selbst ist in der Regel eine indirekte (oder symbolischen) Referenz, die Benennung der current-Zweig, und die gespeicherte ID unter der Zweig-name ist dann der aktuelle Begehen. Daher, wenn Sie "auf branch "master", alsgit status
sagen würde—in anderen Worten, wenn Sie möchten, haben* master
imgit branch
Ausgabe—dannHEAD
enthält den stringrefs/heads/master
, undrefs/heads/master
enthält die commit-ID. Wenn Sie eine "detached HEAD", obwohlHEAD
nur die raw-commit-hash in es, so dass es keine aktuellen branch name. In diesem "detached HEAD" - Fall, kann es keine upstream-entweder, weil der upstream verbunden ist, um den branch name.git rev-parse $(git rev-list --topo-order --reverse --max-count=1 $new_commit --not --remotes=origin)^
was bekommt der Elternteil, der den höchsten Begehen in der Geschichte der new_commit, dass ist nicht auf die in origin. Das würde funktionieren, aber nur, wenn die neue commit-Wurzeln sind eine strikte Untermenge der Ursprung, die Wurzeln.origin
gibt es nichts zu fusionieren mit. Sie müssen Fragen, die Git zum festlegen einer Verzweigung Namen gibt, sagt er, die sich dazu verpflichten, um es —und definitionsgemäß können Sie nur bitten, das er seine Zweig-namefoo
zeigen einige Begehen, die Sie bereits haben, weil Sie Fragen von hash-ID aus, verpflichtet Sie haben. Diese werden verpflichtet, dass Sie, dass Sie noch nicht: Sie senden Ihnen diese begeht mitgit push
, und als der Letzte Teil dergit push
haben, bitten Sie Sie, um den Namen als auch. [Fortsetzung]foo
verbindet an einem gewissen Punkt, um einige der Geschichte, die Sie bereits haben, D. H., besteht nicht nur all-commits (sobald wir Folgen zu Begehen, um seine Eltern und deren Eltern und so weiter). Ist das richtig?new_commit
auseinander. Im Beispiel habe ich gepostet,git merge-base origin/branch2 commitish
gibt commit-X, die ist, was ich will, abergit merge-base master commitish
zurück, verpflichten branch2-Gabel aus.push
einführen, die nur zwei neue ordentliche begeht und, dass wir die Dritte zurück, die den Namenorigin/startpoint
in unsere lokale Kopie, leicht. Wenn wir jetztgit diff origin/startpoint foo
wir sehen überhaupt keine Veränderung. Aber in der Tat, die erste neuen commit changes everything, enthüllt alle Arten von geheimen Passwörtern, und die zweite änderung ist ein revert rückgängig zu machen. Wir werden es vermissen, alle wichtigen Sachen!foo
sind nicht erreichbar von jedemorigin/*
label; wenn Sie ausgeführt habengit fetch
vor kurzem, das sind die commits, die am ehesten geschoben werden (aber das wird miss begeht Sie erreichen durch Ihre tags: brauchen Sie "remote-tags", um auszuschließen, diese so gut). Man könnte dann untersuchen Sie solche begeht, um zu sehen, welche Daten Sie versenden.--not --all
(nicht 100% perfekt, aber ausreichend). Siehe web.torek.net/torek/git/pre-receive.sh.txt für einen mäßig komplexen Beispiel pre-receive hook (scannt nicht verpflichtet wäre).