it-swarm.com.de

Den Unterschied der Verzweigung zwischen SVN und Git verstehen

Ich bin ein Benutzer von SVN und jetzt lerne ich Git.

In SVN checke ich normalerweise auf meinem lokalen Computer ein Repo aus, das alle Zweige in meinem Projekt enthält, und habe den Ordner für meinen Zweig ausgewählt, an dem ich interessiert bin, und dort gearbeitet.

Ich sehe einen Unterschied bei der Verwendung von Git.

Derzeit klone ich ein Repo und klone einen bestimmten Zweig mit gitk.

Der Projektordner enthält nur den Inhalt für diesen Zweig und ich kann nicht alle Zweige wie in SVN sehen, was für mich etwas verwirrend ist.

Ich kann mit Git nicht einfach alle Zweige in meinem lokalen Repository anzeigen.

  • Ich würde gerne wissen, ob der von mir beschriebene Git-Prozess "Standard" ist und wie richtig oder ob mir etwas fehlt.

  • Außerdem möchte ich wissen, wie ein Prozess zu handhaben ist, bei dem ich gleichzeitig an zwei Zweigen arbeiten muss, falls ich beispielsweise einen Hotfix auf dem Master erstellen muss, aber auch den Inhalt eines anderen Zweigs behalten möchte.

  • Was ist eine empfohlene Namenskonvention, um die Ordner zu erstellen, die den aus dem Repo in Git geklonten Zweig enthalten, Beispiel myproject-branchname?

47
Radex

Ich bin ein Benutzer von SVN und jetzt lerne ich GIT.

Willkommen in der Bande!

SVN Umerziehung

In SVN habe ich normalerweise [...]

Warte einen Moment. Während CVS und SVN und andere traditionelle (dh zentralisierte) Versionskontrollsysteme (meistens) denselben Zweck erfüllen wie moderne (dh verteilte) Versionskontrollsysteme wie Mercurial und Git, sollten Sie Git viel besser von Grund auf lernen als versuchen, Ihren SVN-Workflow auf Git zu übertragen.

http://hginit.com ( Ansicht auf archive.org ) von Joel Spolsky (einer der Gründer von Stack Exchange) ist ein Tutorial für Mercurial, nicht für Git, Aber es ist das nullte Kapitel, "Subversion Re-Education" ist nützlich für Leute, die von SVN zu any verteilten Versionskontrollsystemen wechseln, da es Ihnen sagt, welche SVN Konzepte müssen Sie (vorübergehend) un - lernen (oder stash away , wie es Git-Benutzer könnten sagen), um sich mit den Konzepten des verteilten Versionskontrollsystems und den idiomatischen Workflows, die für die Arbeit mit ihnen eingerichtet wurden, vertraut zu machen.

Sie können also das nullte Kapitel lesen und meistens nur das Wort "Mercurial" durch "Git" ersetzen und sich und Ihren Verstand richtig auf Git vorbereiten.

Das Kleingedruckte

(Sie können dies vorerst überspringen.) Während Mercurial und Git einander viel ähnlicher sind als SVN, gibt es sind einige konzeptionelle Unterschiede zwischen ihnen, Daher werden einige der Aussagen und Ratschläge in "Subversion Re-Education" technisch falsch, wenn "Mercurial" durch "Git" ersetzt wird:

  • Während Mercurial Änderungssätze intern verfolgt und speichert, verfolgt und speichert Git intern Revisionen (d. H. Zustände des Inhalts eines Verzeichnisbaums), genau wie Subversion. Aber außer Subversion Git führt Zusammenführungen durch, indem es die Unterschiede zwischen den einzelnen beteiligten Zweigen und einer gemeinsamen Ahnenrevision untersucht ( eine echte 3-Punkt-Zusammenführung), daher ist das Ergebnis ähnlich wie bei Mercurial: Das Zusammenführen ist viel einfacher und weniger fehleranfällig als bei SVN.
  • Während Sie können in Git verzweigen, indem Sie das Repository klonen (wie es in Mercurial üblich ist), ist es weitaus üblicher, einen neuen Zweig in einem Git-Repository zu erstellen. (Dies liegt daran, dass Git-Zweige lediglich (sich bewegende) Zeiger auf Revisionen sind, während Mercurial-Zweige permanente Beschriftungen sind, die auf jede Revision angewendet werden. Diese permanenten Beschriftungen sind normalerweise unerwünscht. Daher funktionieren Mercurial-Workflows normalerweise, indem das gesamte Repository für unterschiedliche Entwicklungen geklont wird.)

In SVN ist alles ein Verzeichnis (aber Sie sollten es nicht unbedingt als solches behandeln).

Aber ich habe dich unterbrochen. Du hast gesagt?

In SVN checke ich normalerweise auf meinem lokalen Computer ein Repo aus, das alle Zweige in meinem Projekt enthält, und habe den Ordner für meinen Zweig ausgewählt, an dem ich interessiert bin, und dort gearbeitet.

Wenn Sie damit meinen, dass Sie den Stammordner des SVN-Repositorys (oder einen anderen Ordner, der mehr als trunk oder einem einzelnen Zweig entspricht, ausgecheckt haben, z. B. im herkömmlichen SVN-Repo-Layout das branches Ordner, der alle Nicht-Trunk-Zweige enthält), dann wage ich zu sagen, dass Sie wahrscheinlich SVN falsch (ish) verwendet haben oder zumindest ein bisschen missbraucht haben, dass Trunk, Zweige und Tags alle zu einem einzigen zusammengefasst sind (obwohl hierarchisch). Namespace zusammen mit Verzeichnissen innerhalb die Revisionen/Codebasis.

Während es verlockend sein könnte, mehrere SVN-Zweige parallel zu ändern, ist dies AFAIK, nicht wie SVN verwendet werden soll. (Obwohl ich mir nicht sicher bin, welche spezifischen Nachteile das haben könnte.)

In Git sind nur Verzeichnisse Verzeichnisse

Jeder Klon eines Git-Repositorys ist selbst ein Git-Repository: Standardmäßig erhält er eine vollständige Kopie des Origin-Repository-Verlaufs, einschließlich aller Revisionen, Zweige und Tags. Aber alles bleibt Ihnen im Weg: Git speichert es in einer Art dateibasierter Datenbank, die sich im versteckten Unterordner .git/ Des Stammverzeichnisses des Repositorys befindet.

Aber was sind die nicht versteckten Dateien, die Sie im Repository-Ordner sehen?

Wenn Sie git clone Ein Repository verwenden, führt Git verschiedene Aktionen aus. Grob:

  1. Es erstellt den Zielordner und darin den Unterordner .git/ Mit der "Datenbank".
  2. Es überträgt die Referenzen (Tags, Zweige usw.) der Origin-Repository-Datenbank und erstellt eine Kopie davon in der neuen Datenbank, wodurch sie geringfügig geändert werden Name, der sie als "entfernte" Referenzen kennzeichnet.
  3. Es überträgt alle Revisionen (dh Dateibaumzustände), auf die diese Referenzen verweisen, sowie alle Revisionen, auf die diese Revisionen direkt oder transitiv verweisen (ihre Eltern) und Vorfahren) in die neue Datenbank und speichert sie, sodass die neuen Remote-Referenzen tatsächlich auf etwas verweisen, das im neuen Repository verfügbar ist.
  4. Es wird ein lokaler Zweig erstellt, der die Remote-Revision verfolgt, die dem Standardzweig des Origin-Repositorys entspricht (normalerweise master).
  5. Es überprüft diesen lokalen Zweig.

Dieser letzte Schritt bedeutet, dass Git die Revision, auf die dieser Zweig verweist, nachschlägt und den dort gespeicherten Dateibaum (die Datenbank verwendet Komprimierungs- und Deduplizierungsmethoden) in den Stammordner des Repositorys entpackt. Dieser Stammordner und alle seine Unterordner (mit Ausnahme des speziellen Unterordners .git) Werden als "Arbeitskopie" Ihres Repositorys bezeichnet. Hier interagieren Sie mit dem Inhalt der aktuell ausgecheckten Revision/Verzweigung. Es sind nur normale Ordner und Dateien. Um jedoch mit dem Repository an sich (der "Datenbank" der Revisionen und Referenzen) zu interagieren, verwenden Sie git Befehle.

Anzeigen von Git-Zweigen und Interagieren mit Git-Zweigen

Derzeit klone ich ein Repo und klone einen bestimmten Zweig mit gitk.

Die Version von gitk , die ich erhalten habe, kann keine Repositorys klonen. Es kann nur den Repo-Verlauf anzeigen, Zweige erstellen und Zweige auschecken. Es gibt auch kein "Klonen" eines Zweigs. Sie können nur Repositorys klonen.

Meinten Sie, Sie klonen ein Repo mit git clone ... und dann mit gitk auschecken ein Zweig?

Der Projektordner enthält nur den Inhalt für diesen Zweig und ich kann nicht alle Zweige wie in SVN sehen, was für mich etwas verwirrend ist.

[...]

  • Ich würde gerne wissen, ob der von mir beschriebene Git-Prozess "Standard" ist und wie richtig [...]

Ja, das ist ziemlich normal:

  • Klonen Sie ein Repository mit git clone ...
  • Schauen Sie sich den Zweig an, an dem Sie arbeiten möchten git checkout ... Oder verwenden Sie ein grafisches Tool wie gikt

Ich kann mit GIT keine einfache Möglichkeit finden, alle Zweige in meinem lokalen Repository anzuzeigen.

  • [...] oder ich vermisse smt.

Könnte sein:

  • sie können lokale Niederlassungen mit git branch auflisten.
  • sie können entfernte Zweige mit git branch -r oder alle Zweige mit git branch -a auflisten.
  • sie können gitk verwenden, um den vollständigen Verlauf (alle Zweigstellen-Tags usw., über die Ihr lokales Repo Bescheid weiß) anzuzeigen, indem Sie ihn mit aufrufen

    gitk --all
    

So arbeiten Sie mit mehreren Zweigen parallel

  • Außerdem möchte ich wissen, wie ein Prozess zu handhaben ist, bei dem ich gleichzeitig an zwei Zweigen arbeiten muss, falls ich beispielsweise einen Hotfix auf dem Master erstellen muss, aber auch den Inhalt eines anderen Zweigs behalten möchte.

Hier gibt es verschiedene Szenarien:

Eine neue (noch zu erstellende) Änderung muss auf mehrere Zweige angewendet werden

Verwenden Sie diesen Workflow:

  1. Erstellen Sie einen neuen Zweig c aus einer Revision, die bereits in der Abstammung all dieser Zweige enthalten ist (z. B. der Revision, die den Fehler eingeführt hat, wenn die Änderung ein Bugfix ist) oder aus einer Revision, die (einschließlich aller ihrer Vorfahren) ist akzeptabel, um in all diesen Zweigen eingeführt zu werden.
  2. Nehmen Sie die Änderung für diesen neuen Zweig vor und übernehmen Sie sie c.
  3. Für jeden Zweig b, der die Änderung benötigt:

    1. Check out b:

      git checkout b
      
    2. Füge c zu b zusammen:

      git merge c
      
  4. Zweig entfernen c:

    git branch --delete c
    

Eine vorhandene Änderung ist in einem anderen Zweig erforderlich

(... aber ohne die anderen Änderungen, die an dem Ort vorgenommen wurden, an dem sich diese Änderung befindet)

  1. Überprüfen Sie den Zweig, in dem die Änderung erforderlich ist
  2. Cherry-Pick die Revision (en), die die Änderung vornehmen, in der richtigen Reihenfolge

In einem Zweig a möchten Sie eine oder mehrere Dateien in den genauen Status ändern, den sie in einem anderen Zweig haben b

  1. Check out a
  2. Holen Sie sich den Dateiinhalt von Zweig b:

    git checkout b -- path/to/a/file.txt path/to/another/file.cpp or/even/a/complete/directory/ ...
    

    (Anders als git checkout Ohne Übergabe von Pfaden, dies wird nicht zum Zweig b wechseln, nur den angeforderten Dateiinhalt von dort erhalten. Diese Dateien sind möglicherweise bereits in a vorhanden oder nicht. Wenn sie dies tun, werden sie mit ihrem Inhalt auf b überschrieben.)

Während Sie an einem Zweig arbeiten, möchten Sie sehen, wie sich die Dinge in einem anderen Zweig befinden

Überprüfen Sie den Zweig, an dem Sie arbeiten möchten.

Dann, um den anderen Zweig anzusehen,

  • verwenden Sie entweder grafische Tools, mit denen Sie den Inhalt nicht aktuell ausgecheckter Revisionen anzeigen können (z. B. versuchen Sie in gitk, die Optionsfelder von "Patch" auf "Baum" umzuschalten).
  • oder klonen Sie das Repository in ein temporäres Verzeichnis und überprüfen Sie den anderen Zweig dort
  • oder verwenden Sie git worktree , um ein separates Arbeitsverzeichnis zu erstellen desselben Repositorys (dh verwenden Sie auch die Datenbank im Verzeichnis .git/ Ihres aktuelles lokales Repository), in dem Sie diesen anderen Zweig auschecken können
69
das-g

In SVN checke ich normalerweise auf meinem lokalen Computer ein Repo aus, das alle Zweige in meinem Projekt enthält, und habe den Ordner für meinen Zweig ausgewählt, an dem ich interessiert bin, und dort gearbeitet.

Wenn Sie das Verzeichnis über dem Trunk nicht auschecken, haben Sie in Subversion im Allgemeinen nicht alle lokal verfügbaren Zweige. In Git werden alle Inhalte (Commits, Nachrichten, Zweige usw.) immer auf jede Kopie geklont.

Derzeit klone ich ein Repo und klone einen bestimmten Zweig mit gitk.

Nicht möglich, siehe oben. Du kannst git checkout branch-name, aber du kannst nicht git clone something branch-name. In Subversion sind Zweige Ordner. In Git sind Zweige Zeiger auf ein Commit.

Ich kann mit GIT keine einfache Möglichkeit finden, alle Zweige in meinem lokalen Repository anzuzeigen.

Lauf git branch. Standardmäßig werden nur lokale Zweige angezeigt. Verwenden git branch --remote um entfernte Zweige zu sehen.

31
l0b0

Da dies mit git markiert ist, hoffe ich, dass mein Mangel an SVN-Kenntnissen vernachlässigbar ist.

Derzeit klone ich ein Repo und klone einen bestimmten Zweig mit gitk.

Sie klonen das gesamte Remote-Repository und nicht nur einen bestimmten Zweig.

Das Repository lässt sich am besten als Datenbank vorstellen, sodass Sie einen Klon des aktuellen Status der entfernten Datenbank erstellen. Danach arbeiten Sie an Ihrer eigenen Kopie dieser Datenbank. Wenn Sie ein Commit durchführen, ändern Sie Ihre lokale Datenbank.

Der Befehl fetch wird verwendet, um die lokale Datenbank mit der entfernten Datenbank synchron zu halten.

Normalerweise checken Sie aus dieser lokalen Datenbank einen Zweig aus, an dem Sie arbeiten möchten. Dies ist nichts anderes als ein interner Marker für Git, an dem Ihre aktuelle Arbeit begann.

Angenommen, Sie arbeiten an einem einfachen Repository, in dem es außer master keinen Zweig gibt. Sie können einen Blick in den Ordner .git Werfen, um die "Magie" zu enthüllen:

Angenommen, Ihr letztes Commit (auf master) war 182e8220b404437b9e43eb78149d31af79040c66, Genau das finden Sie unter cat .git/refs/heads/master.

Wenn Sie einen neuen Zweig git checkout -b mybranch Verzweigen, finden Sie genau den gleichen Zeiger in der Datei cat .git/refs/heads/mybranch.

Zweige sind nichts anderes als "Zeiger". Der "funktionierende" Marker heißt HEAD.

Wenn Sie wissen möchten, wo sich Ihr HEAD befindet:

cat .git/HEAD, Der z. ref: refs/heads/mybranch, Was wiederum (cat .git/refs/heads/mybranch) Auf einen Commit-Hash 78a8a6eb6f82eae21b156b68d553dd143c6d3e6f Zeigt.

Die eigentlichen Commits werden im Ordner objects gespeichert (das Wie ist ein eigenes Thema).

Der Projektordner enthält nur den Inhalt für diesen Zweig und ich kann nicht alle Zweige wie in SVN sehen, was für mich etwas verwirrend ist.

Verwechseln Sie den working directory Nicht mit der "Git-Datenbank" als Ganzes. Wie ich oben sagte, ist Ihr Arbeitsverzeichnis nur eine Momentaufnahme (vielleicht) einer Teilmenge.

Angenommen, Sie haben verschiedene Zweige, Ihr Arbeitsverzeichnis ist nur für die Arbeit an diesem Zweig vorgesehen (obwohl Sie die Arbeit von dort an anderer Stelle ablegen könnten).

Wenn Sie sehen möchten, welche Zweige für das Projekt definiert sind, haben Sie normalerweise die Möglichkeit

  • git branch Für lokale Niederlassungen
  • git branch --remote Für entfernte Zweige
  • git branch -a Für beide

(oder git branch -v)

Da git ein verteiltes Versionskontrollsystem ist, ist es nicht nur möglich, sondern auch empfohlen, verschiedene Zweige lokal/remote zu erstellen.

Mein typischer Workflow ist:

  • verzweigen Sie eine Feature-Verzweigung
  • verzweigen Sie daraus einen WIP-Zweig (work in progress)
  • arbeiten Sie so, wie Sie möchten - auch wenn Sie nach einer einzelnen Zeile festschreiben. es spielt keine Rolle

Wenn die Funktion abgeschlossen ist:

  • squash/Rework der WIP-Verzweigung (mit interaktiver Neugründung) = mache daraus ein einzelnes Commit
  • führen Sie den Zweig WIP in den Feature-Zweig ein und bieten Sie diesen (wenn Sie mit github arbeiten, wird dieses Angebot als "Pull-Anfrage" bezeichnet) zur Integration in den stabilen (Master-) Zweig an.

Außerdem möchte ich wissen, wie man einen Prozess handhabt, bei dem ich zwei Zweige gleichzeitig bearbeiten muss, falls ich beispielsweise einen Hotfix auf dem Master erstellen muss, aber auch den Inhalt eines anderen Zweigs behalten muss.

Es hängt davon ab, wie Ihr Projekt strukturiert ist:

Angenommen, Sie haben einen stabilen Meister. Und Features werden nur aus diesem stabilen Zweig heraus entwickelt - also normalerweise hinter einem Feature-Zweig. Dann hätten Sie ein letztes Commit für den Master, das die Wurzel des Feature-Zweigs wäre.

Dann würden Sie ein Commit für den Hauptzweig durchführen und könnten entscheiden, ob beide Zweige zusammengeführt oder neu aufgebaut werden sollen (Dies ist sozusagen eine Art Zusammenführung für Benutzer mit fortgeschrittenen Anforderungen).

Oder Sie können jederzeit Änderungen an Zweigen vornehmen (z. B. master) und diese auf andere Zweige übertragen.

Was ist eine empfohlene Namenskonvention, um die Ordner zu erstellen, die den aus dem Repo in GIT geklonten Zweig enthalten, zum Beispiel myproject-branchname

Es liegt an dir.

In der Regel erhalten Sie den Namen des Repositorys.

Aber es gibt Fälle, in denen dies nicht erwünscht ist:

z.B. Sie klonen oh-my-zsh mit git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh Hier wird .oh-my-zsh explizit als Ziel benannt.

3
Thomas Junk

Git clone Klont tatsächlich das gesamte Repository, setzt jedoch Ihr Arbeitsverzeichnis auf den Standardwert (normalerweise Master).

Sie können andere Zweige anzeigen, indem Sie git branch Verwenden, um lokale Zweige anzuzeigen, oder git branch -r, Um entfernte Zweige anzuzeigen, und dann git checkout, Um zu einem vorhandenen Zweig zu wechseln oder einen neuen Zweig basierend auf dem aktuellen zu erstellen Ast.

Sie sollten die Git-Dokumentation lesen, um weitere Details zu erfahren, und Atlassian hat auch einige gute Artikel darüber.

2
HorusKol

Zweige in git und svn sind grundsätzlich verschiedene Dinge.

In svn ist ein Zweig (oder ein Tag) ein Verzeichnis im Repo.

In git ist ein Zweig (oder ein Tag) ein Zeiger auf ein Commit.

Mit svn können Sie, wenn Sie möchten, die Wurzel des Repos auschecken. Dies bedeutet, dass Sie jeden Zweig und jedes Tag gleichzeitig ausgecheckt haben. Dies ist nicht die normale Art, SVN zu verwenden.

Ein Git-Zweig ist kein Verzeichnis, daher gibt es kein Äquivalent zum "Auschecken des Stamms des Repos". Es gibt eine gewisse Unterstützung für mehrere Arbeitsbäume, sodass Sie wahrscheinlich ein Skript zusammenschustern können, um jeden Zweig gleichzeitig auszuchecken, wenn Sie es wirklich wollten, aber es wäre ein ziemlich ungewöhnlicher Gedanke.

Außerdem gibt es bei SVN genau ein Repo. Mit git hat jeder Entwickler sein eigenes Repo. Dies bedeutet, dass Entwickler offline arbeiten können, aber es bedeutet auch, dass verschiedene Entwickler unterschiedliche Vorstellungen davon haben, was sich in den einzelnen Zweigen befindet.

Aufgrund ihrer Verzeichnisse und des einfachen linearen Geschichtsmodells von svn haben svn-Zweige eine robuste Geschichte. Wenn Sie wissen möchten, was sich am Datum y in Zweigstelle x befand, können Sie diese Frage ganz einfach stellen.

Git-Zweige hingegen haben keine wirklichen Geschichten. Es gibt das "Reflog", aber es ist eher als Disaster Recovery-Mechanismus als als langfristige Geschichte gedacht. Insbesondere kann das Reflog nicht remote gelesen werden und ist standardmäßig für nackte Repos deaktiviert.

Commits haben natürlich Historien, aber diese Historien reichen nicht aus, um die Frage zu beantworten, "was sich zum Zeitpunkt z in Zweig x von Repo y befand".

Ich kann mit Git nicht einfach alle Zweige in meinem lokalen Repository anzeigen.

Sie können alle lokalen Zweige auflisten, indem Sie "git branch" eingeben.

Sie können alle lokalen und Remote-Zweige mit "git branch -a" auflisten.

Außerdem möchte ich wissen, wie ein Prozess zu handhaben ist, bei dem ich gleichzeitig an zwei Zweigen arbeiten muss, falls ich beispielsweise einen Hotfix auf dem Master erstellen muss, aber auch den Inhalt eines anderen Zweigs behalten möchte.

Ein paar Möglichkeiten.

Sie können Ihre Änderungen im "anderen Zweig" festschreiben, dort zum Master wechseln, um Ihre Arbeit zu erledigen, und dann zurückwechseln.

Sie können auch einen zusätzlichen Arbeitsbaum erstellen. Google "git-worktree" für die Details zur Syntax.

Was ist eine empfohlene Namenskonvention, um die Ordner zu erstellen, die den aus dem Repo in Git geklonten Zweig enthalten, z. B. myproject-branchname?

Ich glaube nicht, dass es eine etablierte Konvention gibt. Das gleichzeitige Auschecken mehrerer Arbeitsbäume ist die Ausnahme und nicht die Regel.

0
Peter Green