Wie wird Ursprung / KOPF eingestellt?

144

Ich habe einen Zweig eingerichtet, um einen Ref im Ursprung zu verfolgen. git checkout <branchname>wechselt zu diesem Zweig, und ein git statusWille zeigt mir, wie weit vor oder hinter meinem Zweig der Ursprung liegt, aber ich bin überrascht, dass er origin/HEADimmer noch auf origin/masterzeigt und nichtorigin/<branchname>

Meine Frage ist also, unter welchen Umständen wird Ursprung / KOPF bewegt?

BEARBEITEN:

Ich schätze die Antworten, wie man Herkunft / KOPF bewegt, aber ich bin daran interessiert, was "organisch" es bewegt, ohne dass ich es ausdrücklich dazu auffordere.

Wenn ich zum Beispiel einen Zweig wechsle, zeigt git HEAD auf den Zweig, den ich auschecke, und ich bin überrascht, dass sich origin / HEAD nicht auf die gleiche Weise bewegt.

ecoffey
quelle
Beachten Sie, dass es sich bei dieser Frage um lokale symbolische Verweise auf Fernbedienungen handelt, wie z refs/origin/HEAD. Es geht nicht darum, wie die eigene symbolische Referenz eines Repositorys HEADfestgelegt wird.
Clacke

Antworten:

172

Beachten Sie zunächst, dass Ihre Frage ein kleines Missverständnis aufweist. origin / HEAD stellt den Standardzweig auf der Fernbedienung dar , dh den HEAD, der sich in dem Remote-Repository befindet, das Sie origin nennen. Wenn Sie die Filialen in Ihrem Repo wechseln, hat dies keine Auswirkungen. Gleiches gilt für entfernte Zweige. Möglicherweise haben Sie masterund origin/masterin Ihrem Repo, wo origin/mastereine lokale Kopie des masterZweigs im Remote-Repository darstellt.

Der HEAD von origin ändert sich nur, wenn Sie oder eine andere Person ihn tatsächlich im Remote-Repository ändern. Dies sollte grundsätzlich nie passieren. Sie möchten, dass der Standardzweig eines öffentlichen Repos im stabilen Zweig (wahrscheinlich Master) konstant bleibt. origin / HEAD ist eine lokale Referenz, die eine lokale Kopie des HEAD im Remote-Repository darstellt. (Der vollständige Name lautet refs / remotes / origin / HEAD.)

Ich denke, das Obige beantwortet, was Sie eigentlich wissen wollten, aber um fortzufahren und die Frage zu beantworten, die Sie explizit gestellt haben ... origin / HEAD wird automatisch festgelegt, wenn Sie ein Repository klonen, und das war's auch schon. Seltsamerweise wird es nicht durch Befehle wie git remote update- Ich glaube, der einzige Weg, wie es sich ändern wird, ist, wenn Sie es manuell ändern. (Mit Änderung meine ich, auf einen anderen Zweig zu verweisen; offensichtlich zeigt das Festschreiben auf Änderungen, wenn sich dieser Zweig ändert, was beim Abrufen / Ziehen / Remote-Update passieren kann.)


Bearbeiten : Das unten diskutierte Problem wurde in Git 1.8.4.3 behoben ; siehe dieses Update .


Es gibt jedoch eine kleine Einschränkung. HEAD ist eine symbolische Referenz, die auf einen Zweig anstatt direkt auf ein Commit verweist. Die git-Fernübertragungsprotokolle melden jedoch nur Commits für Referenzen. Git kennt also die SHA1 des Commits, auf das HEAD und alle anderen Refs hinweisen. Anschließend muss der Wert von HEAD abgeleitet werden, indem ein Zweig gefunden wird, der auf dasselbe Commit verweist. Das heißt, wenn zwei Zweige dorthin zeigen, ist dies nicht eindeutig. (Ich glaube, es wählt nach Möglichkeit den Master aus und greift dann alphabetisch auf den ersten zurück.) Dies wird in der Ausgabe von git remote show origin:

$ git remote show origin
* remote origin
  Fetch URL: ...
  Push  URL: ...
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    foo
    master

Obwohl sich der auf diese Weise gedruckte Begriff HEAD ändert, wenn sich die Dinge auf der Fernbedienung ändern (z. B. wenn foo entfernt wird), wird er seltsamerweise nicht aktualisiert refs/remotes/origin/HEAD. Dies kann zu sehr merkwürdigen Situationen führen. Angenommen, im obigen Beispiel hat origin / HEAD tatsächlich auf foo gezeigt, und der foo-Zweig von origin wurde dann entfernt. Wir können dann Folgendes tun:

$ git remote show origin
...
HEAD branch: master
$ git symbolic-ref refs/remotes/origin/HEAD
refs/remotes/origin/foo
$ git remote update --prune origin
Fetching origin
 x [deleted]         (none)     -> origin/foo
   (refs/remotes/origin/HEAD has become dangling)

Obwohl Remote Show weiß, dass HEAD Master ist, wird nichts aktualisiert. Der veraltete foo-Zweig ist korrekt beschnitten, und HEAD baumelt (zeigt auf einen nicht vorhandenen Zweig), und es wird immer noch nicht aktualisiert, um auf den Master zu zeigen. Wenn Sie dies beheben möchten, verwenden Sie git remote set-head origin -a, wodurch der HEAD des Ursprungs wie oben automatisch ermittelt wird, und setzen Sie origin / HEAD dann so, dass er auf den entsprechenden Remote-Zweig verweist.

Cascabel
quelle
@jefromi Super Antwort! Nur eine Bemerkung: Sie schreiben, dass HEAD ein symbolischer Verweis ist, der auf einen Zweig anstatt direkt auf ein Commit [...] verweist , aber der Vollständigkeit halber könnte es erwähnenswert sein, "losgelösten HEAD-Status" zu erwähnen.
Jub0bs
2
@Jubobs Danke! Wenn meine Antwort aktualisiert werden muss, können Sie sie einfach bearbeiten. Dies spart den Leuten sicherlich Zeit, eine kurze Zusammenfassung der tatsächlichen Funktionsweise zu lesen, anstatt zu sortieren, was vor zwei Jahren wahr war und was jetzt wahr ist .
Cascabel
habe dies mindestens 5 mal gelesen und verstehe immer noch kein bisschen davon
krb686
7
git remote set-head origin -ahat den Job für mich gemacht
Shujito
75

Dies ist Ihre Einstellung als Eigentümer Ihres lokalen Repos. Ändern Sie es so:

git remote set-head origin some_branch

Und origin / HEAD zeigt auf Ihren Zweig anstatt auf den Master. Dies würde dann nur für Ihr Repo gelten und nicht für andere. Standardmäßig zeigt es auf Master, es sei denn, auf dem Remote-Repo wurde etwas anderes konfiguriert.

Die manuelle Eingabe für den Fernbedienungskopf bietet hierzu einige gute Informationen.

Bearbeiten: um zu betonen: Ohne dass Sie es sagen, wäre der einzige Weg, wie es sich "bewegen" würde, ein Fall wie das Umbenennen des Hauptzweigs , der meiner Meinung nach nicht als "organisch" angesehen wird. Also, ich würde sagen, organisch bewegt es sich nicht.

eis
quelle
1
Die Bearbeitungsbetonung ist hier nicht ganz korrekt. Dies kann sich auch ändern, wenn Sie von einer lokalen Kopie klonen, die sich nicht im Hauptzweig befindet.
mphair
Ich halte einen Klon nicht für "bewegend", aber ich denke, wir können uns nicht
einig sein
24

Was bewegt Ursprung / KOPF "organisch"?

  • git clone Setzt es einmal auf die Stelle, an der sich HEAD befindet
    • Es dient als Standardzweig zum Auschecken nach dem Klonen mit git clone

Was bedeutet HEAD on Origin?

  • Auf nackten Repositorys (häufig Repositorys „auf Servern“) dient es als Markierung für den Standardzweig, da git clonees so verwendet wird
  • Bei nicht nackten Repositorys (lokal oder remote) wird die aktuelle Kasse des Repositorys angezeigt

Was setzt Ursprung / KOPF?

  • git clone holt und setzt es
  • Es wäre sinnvoll, wenn git fetches wie jede andere Referenz aktualisiert würde , aber nicht
  • git remote set-head origin -a holt und setzt es
    • nützlich, um das lokale Wissen darüber zu aktualisieren, was Remote als "Standardzweig" betrachtet

Wissenswertes

  • origin/HEAD kann auch auf einen anderen Wert eingestellt werden, ohne die Fernbedienung zu kontaktieren: git remote set-head origin <branch>
    • Ich sehe keinen Anwendungsfall dafür, außer zum Testen
  • Leider kann nichts HEAD auf der Fernbedienung einstellen
  • Ältere Versionen von git wussten nicht, auf welchen Zweig HEAD auf der Fernbedienung verweist, sondern nur auf welchen Commit-Hash er schließlich verfügt. Daher hat er hoffentlich einen Zweignamen ausgewählt, der auf denselben Hash verweist
Robert Siemer
quelle
Ich hatte den Bezug verloren origin/HEADund Ihre Lösung half. Vielen Dank!
Java_Dode
Ich bin mit der git fetchAktualisierung nicht einverstanden , da damit eine (lokale) Verknüpfung konfiguriert werden kann. Zitieren des Dokuments: "Ein Standardzweig für eine Fernbedienung ist nicht erforderlich, ermöglicht jedoch die Angabe des Namens der Fernbedienung anstelle einer bestimmten Verzweigung." Es wäre seltsam, wenn eine Remote-Änderung lokal konfigurierte Verknüpfungen aktualisieren würde.
Micha Wiedenmann
@MichaWiedenmann Warum sollte das eine lokal konfigurierte Verknüpfung sein? Für eine lokal konfigurierte Verknüpfung origin/HEADist ein schlechter Name. Und das git clonewiderspricht auch einem Remote-Namen als Standard für einen „lokal konfigurierten Zweig“. In nicht nackten Repositorys ist es nicht einmal sinnvoll, den Strom der Fernbedienung zu verwenden HEAD.
Robert Siemer
10

Haftungsausschluss : Dies ist ein Update von Jefromis Antwort , die ich schreibe, um den Neugierigen etwas Zeit zu sparen.

Ich habe vergeblich versucht, (in Git 2.0.1) die remote HEAD is ambiguousNachricht zu replizieren , die Jefromi in seiner Antwort erwähnt; Also habe ich ein bisschen gegraben (indem ich https://github.com/git/git geklont und das Protokoll durchsucht habe). Früher war es das

Determining HEAD is ambiguous since it is done by comparing SHA1s.

In the case of multiple matches we return refs/heads/master if it
matches, else we return the first match we encounter. builtin-remote
needs all matches returned to it, so add a flag for it to request such.

(Commit 4229f1fa325870d6b24fe2a4c7d2ed5f14c6f771vom 27. Februar 2009, gefunden mit git log --reverse --grep="HEAD is ambiguous")

Die fragliche Mehrdeutigkeit wurde jedoch inzwischen aufgehoben :

One long-standing flaw in the pack transfer protocol used by "git
clone" was that there was no way to tell the other end which branch
"HEAD" points at, and the receiving end needed to guess.  A new
capability has been defined in the pack protocol to convey this
information so that cloning from a repository with more than one
branches pointing at the same commit where the HEAD is at now
reliably sets the initial branch in the resulting repository.

(Commit 9196a2f8bd46d36a285bdfa03b4540ed3f01f671vom 8. November 2013, gefunden mit git log --grep="ambiguous" --grep="HEAD" --all-match)

Bearbeiten (danke an torek ):

$ git name-rev --name-only 9196a2f8bd46d36a285bdfa03b4540ed3f01f671
tags/v1.8.4.3~3

Dies bedeutet, dass Sie bei Verwendung von Git v1.8.4.3 oder höher nicht auf ein mehrdeutiges Remote-HEAD-Problem stoßen sollten.

jub0bs
quelle
1
Basierend auf den Tags in der Git-Quelle gilt dieser Fix für Git-Version 1.8.4.3 und höher.
Torek
@ RobertSiemer Ich bin mir nicht sicher, aber ich denke schon, ja.
Jub0bs
8

Denken Sie daran, es gibt zwei unabhängige Git-Repos, über die wir sprechen. Ihr lokales Repo mit Ihrem Code und der Fernbedienung, die woanders ausgeführt wird.

Sie haben Recht, wenn Sie einen Zweig wechseln, zeigt HEAD auf Ihren aktuellen Zweig. All dies geschieht auf Ihrem lokalen Git-Repo. Nicht das Remote-Repo, das einem anderen Entwickler gehören könnte oder sich auf einem Server in Ihrem Büro oder Github oder einem anderen Verzeichnis im Dateisystem befindet, oder so weiter.

Ihr Computer (lokales Repo) hat nichts damit zu tun, den HEAD-Zeiger auf dem Remote-Git-Repo zu ändern. Es könnte beispielsweise einem anderen Entwickler gehören.

Eine weitere Sache, die Ihr Computer als origin / XXX bezeichnet, ist das Verständnis Ihres Computers für den Status der Fernbedienung zum Zeitpunkt des letzten Abrufs.

Was würde also "organisch" Origin / HEAD aktualisieren? Es wäre Aktivität auf dem Remote-Git-Repo. Nicht dein lokales Repo.

Die Leute haben erwähnt

git symbolic-ref HEAD refs / head / my_other_branch

Normalerweise wird dies verwendet, wenn auf einem Server ein gemeinsames zentrales Git-Repo zur Verwendung durch das Entwicklungsteam vorhanden ist. Dies wäre ein Befehl, der auf dem Remotecomputer ausgeführt wird. Sie würden dies als Aktivität auf dem Remote-Git-Repo sehen.

Pablo Maurin
quelle
1
Entschuldigung, wenn ich mich ein wenig wiederhole. Ich möchte nur darauf hinweisen, dass git ein verteiltes Versionskontrollsystem ist und als solches die beiden Repos unabhängig sind.
Pablo Maurin
3

Führen Sie die folgenden Befehle über die Git-CLI aus:

# move to the wanted commit
git reset --hard <commit-hash> 

# update remote
git push --force origin <branch-name> 
Yakir GIladi Edry
quelle
1
Großartig, das hat mir geholfen!
Shay Zambrovski