Der checkout
Befehl unterscheidet zwei Fälle (eigentlich „viele“, aber lassen Sie uns mit nur den beiden :-) Start):
- „Ich will ’ auf einem Zweig zu ‘ bekommen, hier ist ein Zweigname ": zB
git checkout branch
.
- "Ich möchte eine bestimmte Revision betrachten, und aus jeder Zweig; Hier ist ein Zweig-Kennung, die kein Zweig-Name ist": z. B.
git checkout 6240c5c
.
(Ich persönlich denke, diese verschiedenen Befehlsnamen verwenden sollten, aber das ist nur meine Meinung. Auf der anderen Seite wäre es all die Verrücktheit unten beschrieben beseitigen.)
Nun lassen Sie uns sagen, dass Sie das wollen ehemalige. Das Schreiben ist am einfachsten, wenn Sie einfach den Zweignamen ohne den refs/heads/
Teil schreiben.
Wenn Sie letztere wollen, können Sie eine Überprüfung durch eine der Methoden in gitrevisions aufgelistet angeben, außer für jede Methode, die in „auf dem Zweig bekommen“ führt.
Aus welchem Grund auch immer gewählt der Algorithmus hier-es in der manual page dokumentiert ist, unter <branch>
-is dies: Wenn Sie einen Namen geschrieben haben, dass, wenn refs/heads/
es, Namen ein Zweig hinzufügen, wird git checkout
Sie setzen "auf diesem Zweig". Wenn Sie @{-N}
oder -
angeben, wird die N -te ältere Verzweigung in der HEAD
Reflog (mit -
Bedeutung @{-1}
) nachschlagen. Andernfalls wählt es die zweite Methode und gibt Ihnen den "abgetrennten HEAD". Dies gilt auch dann, wenn der Name in gitrevisions zur Vermeidung von Mehrdeutigkeit vorgeschlagen wird, d. H. heads/xyz
, wenn es einen anderen xyz
gibt. (Aber: Sie können --detach
hinzufügen, um den Fall zu vermeiden, selbst wenn es sonst auf den Zweig kommt.)
Dies widerspricht auch den im gitrevisions-Dokument aufgelisteten Auflösungsregeln.Um dies zu demonstrieren (obwohl es schwer zu sehen ist), habe ich einen Tag und Zweig mit dem gleichen Namen, derp2
:
$ git checkout derp2
warning: refname 'derp2' is ambiguous.
Previous HEAD position was ...
Switched to branch 'derp2'
Das brachte mich auf dem Zweig, anstatt lösen und gehe in der getaggt Revision.
$ git show derp2
warning: refname 'derp2' is ambiguous.
...
Dies zeigte mir die getaggte Version, die Art und Weise wie gitrevisions es sagt.
Eine Randbemerkung: „auf einem Zweig immer“ wirklich bedeutet, „einen symbolischen Verweis auf einen Zweig Namen in die HEAD
im git Verzeichnis mit dem Namen Datei setzen“. Die symbolische Referenz ist der Literaltext ref:
(mit nachhängendem Leerzeichen), gefolgt von dem vollständigen Verzweigungsnamen, z. B. refs/heads/derp2
. Es scheint irgendwie inkonsistent, dass git checkout
fordert den Namen ohne den refs/heads/
Teil, um den ref: refs/heads/
Teil hinzuzufügen, aber das ist Git für Sie. :-) Es gibt vielleicht einen historischen Grund dafür: Ursprünglich war die HEAD
Datei eine symbolische Verbindung zur Datei, die immer eine Datei war. In diesen Tagen, teilweise aufgrund von Windows und teilweise nur durch Code-Evolution, hat es diese literale ref:
Zeichenkette, und Verweise können "gepackt" werden und daher sowieso nicht als separate Datei verfügbar sein.
Umgekehrt bedeutet ein "losgelöster HEAD" wirklich "eine rohe SHA-1 in die HEAD
Datei einfügen". Abgesehen davon, dass git in dieser Datei einen numerischen Wert hat, verhält sich git genauso wie bei "auf einem Zweig": Das Hinzufügen eines neuen Commits funktioniert immer noch, wobei das übergeordnete Element des neuen Commits das aktuelle Commit ist. Zusammenführungen können auch weiterhin durchgeführt werden, wobei die Eltern des Zusammenführungs-Commits die aktuellen und zu verschmelzenden Commits sind. Die Datei HEAD
wird bei jedem neuen Commit aktualisiert. Zu jedem Zeitpunkt können Sie eine neue Verzweigung oder Tag-Beschriftung erstellen, die auf die aktuelle Festschreibung verweist, damit die neue Kette von Festlegungen auch nach dem Ausschalten des "abgetrennten HEAD" gegen zukünftige Speicherbereinigung erhalten bleibt. oder Sie können einfach wegschalten und die neuen Commits, falls vorhanden, mit der üblichen Müllsammlung entfernen lassen. (Beachten Sie, dass die HEAD
reflog dies seit einiger Zeit verhindern wird, 30 Tage Verzug, denke ich.)
[ Wenn Sie „auf einem Zweig“ sind, das gleiche Auto-Update passiert, es passiert einfach zu Der Zweig HEAD
bezieht sich auf. Das heißt, wenn Sie auf Zweig sind B
und Sie fügen ein neues Commit hinzu, HEAD
sagt immer noch ref: refs/heads/B
, aber jetzt die Commit-ID, die Sie mit git rev-parse B
erhalten, ist das neue Commit, das Sie gerade hinzugefügt haben. So wachsen Verzweigungen: Neue Commits, die hinzugefügt werden, während "auf der Verzweigung" die Verzweigungsreferenz automatisch vorwärts bewegt. Wenn sich in diesem Status "Abgelöste HEAD" befinden, führen neue Commits dazu, dass HEAD
automatisch weitergeht.
]
Für Vollständigkeit, hier ist eine Liste von anderen Dingen git checkout
tun kann, dass ich in verschiedenen separaten Befehlen gesetzt haben könnte, wenn ich solche Kräfte habe:
- Prüfung eine bestimmte Version eines -Pfad (s), über den Index zu schreiben:
git checkout revspec -- path ...
- eine Niederlassung erstellen:
git checkout -b newbranch
(plus Optionen für git branch
)
- erstellen Sie einen neuen Zweig, der, ob und wann Sie begehen ein auf sie, werden es tun ein Root-Commit sein:
git checkout --orphan
(dies bringt Sie auf eine Verzweigung, die noch nicht existiert, d. h. schreibt ref: refs/heads/branch-name
in HEAD
, erzeugt aber nicht die Verzweigung branch-name
; dies ist auch, wie master
ein ungeborener Zweig ist in einem neuen Repository)
- erstellen oder neu erstellen eine Zusammenführung oder fusioniert Konflikt:
git checkout -m ...
- lösen einen Merge-Konflikt durch Kommissionierung eines oder die andere „Seite“ des merge:
git checkout --ours
, git checkout --theirs
- interaktiv auswählen Patches zwischen Repository-Objekten und Arbeit Baum Dateien, ähnlich wie
git add --patch
: git checkout --patch
Wow! Danke für die ausführliche Antwort. Du weißt, dass es eine gute Antwort ist, wenn du am Ende noch mehr Fragen hast ;-) Warum glaubt Git, dass die Angabe der Datei in 'refs/heads /' bedeutet, dass ich nicht "auf einen Ast" gehen will? Und außerdem, warum, wenn ich eine beliebige Datei mit einem SHA-1 darin anlege, macht git nicht dasselbe wie für die Dateien in 'refs/heads /'? Es scheint nur inkonsistent ... – darthbith
Eine Verzweigung ist eine lokale Commit-Referenz, die 'git commit' aktualisiert, wenn' HEAD' daran angehängt ist, das ist alles. Zweige leben in 'refs/heads'. 'git checkout' fügt nur 'HEAD' hinzu, aber das will man nicht immer tun. Ob die Schreibweise 'refs/heads/master' behandelt werden soll, sollte wie eine (nicht-verzweigte) Checkbox mit beliebigem Commit behandelt werden, denn wenn Sie die Verzweigungs-Checkouts hätten, hätten Sie gerade' master' gesagt oder sollten wie eine Verzweigung behandelt werden Checkout, weil Sie, wenn Sie einen Non-Branch-Checkout wollten, sagten "Master^0" ist ein Urteilsspruch, ich denke, es gibt gute Argumente in beide Richtungen. – jthill
Ich stimme mit Jthill überein. Manche Dinge schreien wirklich nach "Abhebung", andere schreien nach "Abzweigung", und einige, es ist nur eine Art willkürliche Pause, die jemand einlegt: "A bedeutet auf dem Zweig, B bedeutet Abtrennen vom Zweig". Wenn dies verschiedene Befehle wären ("git switchtobranch", "git detachcheckout" oder was auch immer), müssten Sie nicht willkürlich sein, Sie würden es entweder tun, weil es möglich ist, oder ablehnen, weil es nicht möglich ist. – torek