Wechseln Sie den Git-Zweig ohne Auschecken von Dateien

100

Ist es in Git möglich, zu einem anderen Zweig zu wechseln, ohne alle Dateien auszuchecken?

Nach dem Zweigwechsel muss ich alle Dateien löschen, neu generieren, festschreiben und zurückschalten. Das Auschecken von Dateien ist also nur Zeitverschwendung (und es gibt ungefähr 14.000 Dateien - es ist ein langer Vorgang).

Um alles klar zu machen:

Ich brauche das alles, um Dokumentation auf GitHub hochzuladen .

Ich habe ein Repository mit dem Zweig gh-pages . Wenn ich die Dokumentation lokal neu erstelle, kopiere ich sie in das Repository-Verzeichnis, schreibe sie fest und drücke sie an GitHub. Aber ich war nicht glücklich, weil ich zwei Kopien der Dokumentation vor Ort hatte. Und ich habe beschlossen, einen leeren Zweig zu erstellen und nach dem Festschreiben zu leeren Dateien zu wechseln und diese zu löschen. Das Zurückschalten ist jedoch ein langer Vorgang - daher habe ich diese Frage gestellt.

Ich weiß, dass ich einfach auf dem Gh-Pages- Zweig bleiben und Dateien löschen kann, aber ich mag keine schmutzig arbeitenden Bäume.

tig
quelle
Wie lange ist "lang" für dich? An welcher Plattform arbeiten Sie? Arbeiten Sie über ein Netzwerk wie NFS oder eine andere Dateifreigabe?
Greg Hewgill
Was ist der Zweck dieser Übung? Möchten Sie zwei Zweige haben, einen mit detaillierten Commits und einen, der nur größere Änderungen aufzeichnet (grobkörnig)?
Jakub Narębski
Vielleicht ist es billiger, einen temporären (oder permanenten?) Klon Ihrer Arbeitskopie zu erstellen. Meine entsprechende Antwort und eine Beschreibung zeigen, wie dies auch als Unterverzeichnis des Hauptrepositorys funktioniert.
krlmlr

Antworten:

106

Ja, das kannst du machen.

git symbolic-ref HEAD refs/heads/otherbranch

Wenn Sie einen Commit für diesen Zweig durchführen müssen, möchten Sie auch den Index zurücksetzen, da Sie sonst etwas festschreiben, das auf dem zuletzt ausgecheckten Zweig basiert.

git reset
CB Bailey
quelle
1
Verwenden Sie echo "ebff34ffb665de0694872dceabe0edeaf50ec5a9" > .git/HEADgefolgt von git reset, um auf einen Verweis anstelle eines Zweigs zu zeigen.
Cadorn
1
Das direkte Schreiben in die HEAD-Datei ist weniger zuverlässig. Was ist, wenn Sie in einem Unterverzeichnis sind? Für abgenommenen Kopf (Kopf zeigt direkt auf SHA1), versuchen Sie Folgendes: git update-ref HEAD refs/heads/otherbranch
Alexander Bird
2
Wenn Sie zu einem neuen Zweig aus dem aktuellen Zweig auschecken möchten, ist eine andere Möglichkeit, dies zu tun, 1. git stash2. git checkout -b otherBranch3.git stash pop
Winny
@AlexanderBird: git update-refist nützlich, verschiebt aber auch die Spitze des aktuellen Zweigs.
Tomékwi
47

Verwenden Sie nur grundlegende Git-Befehle:

Diese Antwort ist etwas länger als die von Charles, besteht jedoch ausschließlich aus grundlegenden Git-Befehlen, die ich verstehen und somit merken kann, sodass ich nicht mehr nachschlagen muss.

Markieren Sie Ihren aktuellen Standort (bei Bedarf zuerst festschreiben):

git checkout -b temp

Setzen Sie den Marker zurück in den anderen Zweig, ohne das Arbeitsverzeichnis zu ändern:

git reset <branch where you want to go>

Jetzt verweisen Temp und andere Verzweigungen auf dasselbe Commit, und Ihr Arbeitsverzeichnis bleibt unberührt.

git checkout <branch where you want to go>

Da Ihr HEAD bereits auf dasselbe Commit zeigt, wird das Arbeitsverzeichnis nicht berührt

git branch -d temp

Beachten Sie, dass diese Befehle auch von jedem grafischen Client verfügbar sind.


quelle
7
Ich würde es vorziehen git reset --soft <branch where you want to go>, die Aktualisierung des Index zu vermeiden
JoelFan
7
Ich stimme Ihrer Strategie zu, die Git-Sanitär-Befehle zu vermeiden und die Porzellan-Befehle zu bevorzugen.
user64141
26

In v2.24 git switchist so etwas wie ein Safe git checkout.
Daher umbenannt ich die Alias unten git hopfür
„Hop auf dem Zweig ohne worktree Ändern“

Zum Nutzen des Lesers:

Während ich denke, dass die Lösung von Charles Bailey die richtige ist, muss diese Lösung angepasst werden, wenn zu etwas gewechselt wird, bei dem es sich nicht um eine lokale Niederlassung handelt. Es sollte auch eine Möglichkeit geben, dies mit regulären Befehlen zu tun, was leicht zu verstehen ist. Folgendes habe ich mir ausgedacht:

git checkout --detach
git reset --soft commitish
git checkout commitish

Erklärt:

  • git checkout --detachist das gleiche wie das, git checkout HEAD^{}was den aktuellen Zweig hinterlässt und in den "losgelösten Kopfzustand" übergeht. Die nächste Änderung HEADbetrifft also keinen Zweig mehr. Das Trennen HEADwirkt sich weder auf den Arbeitsbaum noch auf den Index aus.
  • git reset --soft commitishbewegt sich dann HEADzum SHA des Gegebenen commitish. Wenn Sie auch den Index aktualisieren möchten, lassen Sie ihn --softweg, aber ich empfehle dies nicht. Dies berührt wiederum nicht den Arbeitsbaum und ( --soft) nicht den Index.
  • git checkout commitishhängt dann wieder an HEADden gegebenen commitish(Zweig) an. (Wenn commitishes sich um eine SHA handelt, passiert nichts.) Auch dies wirkt sich weder auf den Index noch auf den Arbeitsbaum aus.

Diese Lösung akzeptiert alles, was sich auf ein Commit bezieht, daher ist dies für einige gitAlias ideal . Dasrev-parse Folgende ist nur ein Test, um sicherzustellen, dass nichts in der Kette bricht, sodass Tippfehler nicht versehentlich in den Zustand des abgetrennten Kopfes wechseln (Fehlerbehebung wäre viel komplexer).

Dies führt zu folgendem git hop treeishAlias:

git config --global alias.hop '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f'

Zu Ihrer Information, Sie finden es in meiner Liste der gitAliase .

Tino
quelle
Willst du nicht $@lieber verwenden als $*? Der Unterschied besteht darin, dass $ @ nicht erweiterte Anführungszeichen enthält, die Leerzeichen enthalten.
Kyb
1
@kyb Der Funktionstrick wird aus einer anderen SO-Antwort gestohlen . Und $@ist hier definitiv nicht gemeint. $*wird stattdessen verwendet $1, so dass git switch -f bdas gleiche wird, git switch '-f b'was ein Fehler sein sollte. Auf diese Weise kann ich den Alias ​​verkürzen, indem ich einige Fehlerbehandlungen wie!f() { [ 1 = $# ] || { echo 'WTF!'; return 1; }; ..
Tino
Sehr gute Lösung. Insbesondere, dass es für entfernte Filialen verwendet werden kann!
Nils-o-mat
14

Wäre es nicht eine bessere Lösung, zwei Arbeitsverzeichnisse (zwei Arbeitsbereiche) mit einem Repository oder sogar zwei Repositorys zu haben?

Es gibt ein Tool von git-new-workdir im contrib/Abschnitt, das Ihnen dabei hilft.

Jakub Narębski
quelle
Ist git-new-workdir dasselbe wie gits eigener Arbeitsbaumbefehl? Ich verwende Worktree, wenn ich einen Zweig in einen anderen Ordner auschecken möchte (ohne das gesamte Repo klonen zu müssen).
Ryuu
Das git-new-worktreeSkript ist älter als der git worktreeUnterbefehl. Dieser Befehl war nicht verfügbar, als die Antwort geschrieben wurde. Das Skript erfordert beispielsweise Symlink-Unterstützung. IMHO ist es besser, native Unterstützung zu verwenden.
Jakub Narębski
8

Ich denke, Sie suchen nach dem Sanitärbefehl git read-tree. Dadurch wird der Index aktualisiert, es werden jedoch keine Dateien in Ihrem Arbeitsverzeichnis aktualisiert. Angenommen, branchder Name des zu lesenden Zweigs lautet:

Git Read-Tree-Zweig

Wenn Sie sich dann auf den gerade gelesenen Zweig festlegen möchten, müssen Sie außerdem:

git symbolisch-ref KOPF refs / Köpfe / Zweig
Greg Hewgill
quelle
Nein, ich muss nur den Zweig wechseln, keine weiteren Änderungen - also ist symbolic-ref gut genug
tig
read-treegeneriert den Fehler: fatal: Not a valid object name branchwenn es noch keine git switch branchgab
Andry
7

Sie können Ihre HEAD-Datei mit einem anderen Filialnamen überschreiben:

echo "ref: refs / Heads / MyOtherBranch"> .git / HEAD

user157005
quelle
13
Es ist wahrscheinlich besser, den Befehl symbolic-ref zu verwenden, um dies für Sie zu tun: git symbolic-ref HEAD refs/heads/MyOtherBranch kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html
Greg Hewgill
@ GregHewgill, dies ist die einzige mir bekannte Möglichkeit, den HEAD in einen Commit-Hash zu verschieben. Schaffst du das mit git symbolic-ref?
Tomékwi
0

Bei so vielen Dateien ist es möglicherweise am besten, nur zwei Repos zu behalten, eines für jeden Zweig. Sie können Änderungen nach Bedarf hin und her ziehen. Dies wird weniger überraschend sein als der Versuch, mit Git Skorbut-Streiche zu spielen.

Norman Ramsey
quelle
Sie können git-new-worktreedafür stattdessen (in contrib/) verwenden
Jakub Narębski
Ich habe oft etwas Ähnliches gemacht, nämlich mein lokales Verzeichnis zu kopieren, bevor ich als Neuling irgendwelche "gruseligen Git-Sachen" gemacht habe (wie das Wechseln von Zweigen usw.). Ich würde die Leute ermutigen, diesen Weg zu gehen, bis Sie sich in Ihrem Git-Fu sicher fühlen, aber wenn möglich davon wegzugehen. Das Beibehalten von zwei unterschiedlichen Repos ist in Ordnung, fügt jedoch eine zusätzliche Komplikation hinzu und lässt Sie die vielen nützlichen Funktionen von Git (Zusammenführen, Kirschpflücken usw.) nicht nutzen.
David
0

Wenn Sie lediglich versuchen zu ändern, wo ein entfernter Zweig zeigt, können Sie dies mit "git push" tun, ohne Ihre lokale Kopie zu berühren.

http://kernel.org/pub/software/scm/git/docs/git-push.html

Das Format eines <refspec> -Parameters ist ein optionales Pluszeichen +, gefolgt von der Quellreferenz <src>, gefolgt von einem Doppelpunkt: gefolgt von der Zielreferenz <dst>. Es wird verwendet, um anzugeben, mit welchem ​​<src> -Objekt die <dst> -Referenz im Remote-Repository aktualisiert werden soll.

Um foo zu aktualisieren, um c5f7eba festzuschreiben, gehen Sie wie folgt vor:

git push origin c5f7eba:foo

Ich bin mir nicht sicher, ob du danach gesucht hast oder nicht.

Tim Abell
quelle
Die Frage hat bereits eine Antwort erhalten: stackoverflow.com/questions/1282639/…
tig
0

Sie können nutzen

      1. git checkout -f <new-branch>
      2. git cherry-pick -x <previous-branch-commit-id>

Vorherige-Verzweigungs-Festschreibungs-ID ist die Festschreibung, von der Sie die alten Daten kopieren möchten.

Haseena Parkar
quelle
-1

Angenommen, Sie möchten in Zweig A sein, aber mit den Dateien aus Zweig B.

Finden Sie die aktuelle Commit-Referenz von Zweig A mit Git-Protokoll, z. B. "99ce9a2".

git checkout A
git reset --hard B
git reset 99ce9a2

Sie sollten sich jetzt in Zweig A mit einer Ordnerstruktur befinden, die B entspricht und als nicht bereitgestellte Änderungen angezeigt wird (ein Verlauf hat sich nicht geändert).

Dugas
quelle