{"id":269,"date":"2015-10-22T06:40:20","date_gmt":"2015-10-22T06:40:20","guid":{"rendered":"https:\/\/www.experimini.org\/blog\/?page_id=269"},"modified":"2015-10-22T06:40:20","modified_gmt":"2015-10-22T06:40:20","slug":"git-versionsverwaltung","status":"publish","type":"page","link":"https:\/\/www.experimini.org\/blog\/?page_id=269","title":{"rendered":"GIT Versionsverwaltung"},"content":{"rendered":"<h2>Was ist GIT?<\/h2>\n<p>Git ist eine Sammlung von Werkzeugen zur Versionsverwaltung von Dateien.<br \/>\nIm Laufe der Arbeit an Dateien (z.B. Programm-Code) kann damit jeder Entwicklungsstand eines Projektes festgehalten werden.<\/p>\n<ul>\n<li>Es kann (fast) nichts verloren gehen &#8211; <em>Snapshot<\/em>, <em>History<\/em><\/li>\n<li>Es k\u00f6nnen nebeneinander verschiedene Versionen eines Projekts gepflegt werden (man m\u00f6chte bspw. etwas ausprobieren, was sp\u00e4ter gegebenenfalls in das Projekt aufgenommen werden soll, wenn es erfolgreich getestet wurde) &#8211; <em>Branch<\/em><\/li>\n<li>Jeder Stand der Entwicklung ist referenzierbar und wieder herstellbar &#8211; <em>History<\/em><\/li>\n<li>\n<p>Dezentrale Repositories &#8211; <em>Clones<\/em><\/p>\n<\/li>\n<li>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\">Dokumentation<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>Wozu sollte ich GIT benutzen?<\/h3>\n<p>GIT kann die Koordination von Team-Arbeit an gemeinsamen Projekten unterst\u00fctzen.<\/p>\n<p>GIT bietet aber auch praktische M\u00f6glichkeiten, wenn man es alleine nutzt.<\/p>\n<ul>\n<li>Hilft, \u00dcbersicht zu behalten &#8211; z.B. kein manuelles Abspeichern unter anderem Namen\/Datum n\u00f6tig<\/li>\n<li>Werkzeug zur Dokumentation &#8211; mit gehaltvollen commit messages kann ich die Entstehung meines Projektes sehr gut dokumentieren; alle wichtigen \u00c4nderungen k\u00f6nnen beschrieben und begr\u00fcndet werden; Fehler und &#8220;Sackgassen&#8221; k\u00f6nnen dokumentiert werden.<\/li>\n<li>Unterst\u00fctzt Kreativit\u00e4t &#8211; das Branchen erm\u00f6glicht es, jederzeit ohne Risiko \u00c4nderungen vorzunehmen und zu testen, ohne den &#8220;Haupt-&#8221; Entwicklungszweig zu beeinflussen; da das Branchen in git sehr einfach ist, gew\u00f6hnt man sich schnell an, Branches zu nutzen, um &#8220;mal eben schnell was zu testen&#8221;; bei der Nutzung von Ticket-Systemen k\u00f6nnen Branches die Ticket-Struktur widerspiegeln.<\/li>\n<\/ul>\n<h4>Wof\u00fcr eignet sich git nicht so gut<\/h4>\n<p>Prinzipiell kann mit git jegliches Dateiformat verwaltet werden, allerdings funktionieren <em>diff<\/em>, <em>merge<\/em> etc. am besten mit rein textbasierten Dateiformaten (also Programm-Quelltext, HTML, LaTEX, usw.).<br \/>\nBin\u00e4re Datenformate (Bilder, Audio, Video, komprimierte Textformate (doc)) lassen sich auch mit git verwalten, allerdings kann bei ihnen bspw. ein Merge-Konflikt nur gel\u00f6st werden, indem sich f\u00fcr eine der beiden Versionen entschieden wird, ein Verschmelzen beider Dateien ist nich ohne weiteres m\u00f6glich.<\/p>\n<h3>Was unterscheidet GIT von anderen VCS?<\/h3>\n<ul>\n<li>Git ist Snapshotbasiert, CVS\/SVN ist \u00c4nderungs- (Patch\/Diff)- basiert<\/li>\n<li>Dezentral<\/li>\n<\/ul>\n<h3>Begriffe \/ Konzepte hinter GIT<\/h3>\n<h4>Repository<\/h4>\n<p>Ein Repository ist der &#8220;Beh\u00e4lter&#8221;, in dem das Projekt mitsamt allen seinen Daten, Meta-Informationen und Versionen enthalten ist.<\/p>\n<p>Man unterscheidet zwischen <em>non bare<\/em> Repositories &#8211; sie enthalten einen Arbeitsbereich (also die Dateien an denen gearbeitet werden kann) und <em>bare<\/em> Repositories &#8211; sie enthalten die kompletten Daten und Infos eines Projektes, aber keinen Arbeitsbereich; sie sind sozusagen als Server-Repositories gedacht; in der Regel kann nur in <em>bare<\/em> Repos <em>gepusht<\/em> werden (s.u.).<\/p>\n<h4>Arbeitsbereich (Clone)<\/h4>\n<p>W\u00e4hrend in einigen anderen SCMs zwischen Arbeitsbereich und Repository unterschieden wird, verschwimmen in Git die Grenzen ein wenig. Ein <em>Clone<\/em> eines Repositories enth\u00e4lt immer den kompletten Satz an Informationen \u00fcber das Projekt. Ein <em>Clone<\/em> kann ein &#8220;Arbeitsbereich&#8221; sein oder aber auch als Repository dienen.<\/p>\n<p>Der Arbeitsbereich ist der Ordner, in dem sich mein <em>Clone<\/em> oder mein Projekt befindet. Hier habe ich alle Dateien, die zum Projekt geh\u00f6ren und kann \u00c4nderungen vornehmen.<br \/>\nEin <em>Clone<\/em> ist ein Projekt, das von einem remote Repository &#8216;geholt&#8217; wurde; s\u00e4mtliche Informationen \u00fcber Versionen, Branches etc. sind darin enthalten &#8211; ich verf\u00fcge sozusagen \u00fcber das komplette Projekt mit allen Versionen aller Dateien, die es je gegebn hat.<\/p>\n<h4>(Fetch\/Pull &#8211; Arbeitsbereich updaten)<\/h4>\n<p>Bei der Team-Arbeit an einem Projekt gibt es meist einen oder mehrere Server, auf denen die (Haupt-) Repos liegen, sogenannte &#8216;remotes&#8217;. Zum arbeiten <em>clone<\/em> ich das remote Repo, arbeite daran.<br \/>\nWenn andere Team-Mitglieder auch an dem Projekt arbeiten, entstehen dadurch \u00c4nderungen, die mein <em>Clone<\/em> noch nicht kennt; diese muss ich vom remote anfordern.<br \/>\n<code>git fetch<\/code> holt die Informationen \u00fcber alle seit dem letzten <em>fetch<\/em> geschehenen \u00c4nderungen.<br \/>\n<code>git pull<\/code> <em>merget<\/em> mir die so mitgeteilten \u00c4nderungen in einen bestimmten <em>Branch<\/em><\/p>\n<h4>Staging Area (\u00c4nderungen f\u00fcr Commit vormerken)<\/h4>\n<p>F\u00fcr Neulinge meist etwas verwirrend ist bei git das Konzept der <em>Staging Area<\/em>. Wenn ich in meinem Arbeitsbereich \u00c4nderungen vorgenommen habe, werden diese normalerweise <em>committed<\/em>, i.e. die \u00c4nderungen werden in das Respository \u00fcbernommen.<br \/>\nIn git gibt es jedoch  zuvor eine Zwischenstufe, die <em>Staging Area<\/em>; ein <em>commit<\/em> ber\u00fccksichtigt (im Normalfall) nur alle \u00c4nderungen, die sich in der <em>Staging Area<\/em> (auch <em>Index<\/em>) befinden.<br \/>\nMeine \u00c4nderungen an Dateien in meinem Projekt landen nicht automatisch in der Staging Area, ich muss sie explizit mit einem &#8216;add&#8217; dorthin bef\u00f6rdern.<br \/>\nObwohl das auf den ersten Blick etwas umst\u00e4ndlich erscheint, ist es aber ein m\u00e4chtiges Werkzeug:<\/p>\n<ul>\n<li>Es erlaubt die History &#8211; die Entwicklungsgeschichte des Projektes &#8211; gezielt zu strukturieren und zu dokumentieren (z.B. Ticket-basiert, Feature-basiert, Bugfix-basiert)<\/li>\n<li>Man kann Dateien mit &#8220;privaten&#8221; Notizen versehen (oder bspw. Debug-Ausgaben), ohne diese zu commiten (es l\u00e4sst sich sogar pro Datei zeilenweise ausw\u00e4hlen, was <em>gestaget<\/em> werden soll).<\/li>\n<li>Man kann auch mittels <code>git commit -a<\/code> den ganzen Staging Kram \u00fcberspringen \ud83d\ude09<\/li>\n<\/ul>\n<p><a href=\"http:\/\/git-scm.com\/figures\/18333fig0201-tn.png\">Illustration: Zust\u00e4nde von Dateien<\/a><\/p>\n<h4>Commit (\u00c4nderungen lokal \u00fcbernehmen)<\/h4>\n<p>Mit einem <code>git commit<\/code> \u00fcbernehme ich die <em>gestageten<\/em> \u00c4nderungen in das lokale Repository.<\/p>\n<h4>Push (\u00c4nderungen in ein remote Repo \u00fcbertragen)<\/h4>\n<p>Wenn ich mit einem geclonten Repo arbeite und meine \u00c4nderungen auch den remote Repositories (ich kann beliebig viele remote Repositories verwalten) mitteilen m\u00f6chte, tue ich das mit einem <code>git push<\/code>.<\/p>\n<h4>Branch &#8211; \u00c4nderungszweig erstellen; Neues ausprobieren, altes bleibt bestehen.<\/h4>\n<p>Ein g\u00e4ngiges Verfahren ist, zu Beginn seiner Arbeit einen neuen Zweig, einen Arbeits-Branch zu erstellen, so bleibt mein urspr\u00fcnglicher Branch erhalten und ich kann jederzeit zum Vergleich hin- und her-schalten.<br \/>\nPraktisch ist es auch, w\u00e4hrend der Arbeit ggf. weitere Branches erstellen, um verschiedene Versionen einer \u00c4nderung anzuschauen &#8211; auch wieder ohne Einflussnahme auf den urspr\u00fcnglichen Branch.<br \/>\nNeu angelegte Branches sind zun\u00e4chst &#8220;privat&#8221; &#8211; also nur im lokalen Repo\/Clone &#8211; es sei denn, sie werden explizit in ein remote Repo <em>gepusht<\/em>.<\/p>\n<h4>Merge &#8211; \u00c4nderungszweige zusammenf\u00fchren<\/h4>\n<p>Sind alle \u00c4nderungen zur Zufriedenheit vorgenommen, <em>stage<\/em> und <em>commite<\/em> ich meine Arbeit (noch im Arbeitsbranch). Daraufhin kann ich meinen Arbeitsbranch in den urspr\u00fcnglichen Branch <em>mergen<\/em> &#8211; d.h. Arbeits- und urspr\u00fcnglicher Branch werden zusammengef\u00fchrt.<br \/>\nSind keine weiteren parallelen \u00c4nderungen geschehen, gen\u00fcgt ein <em>Fast Forward Merge<\/em> &#8211; dabei wird nur der HEAD-Zeiger weiterger\u00fcckt.<br \/>\nGab es auch parallele \u00c4nderungen, wird ein <em>3-Wege-Merge<\/em> durchgef\u00fchrt (basierend auf den jeweiligen \u00c4nderungen seit dem letzen gemeinsamen Vorfahren) &#8211; was evtl. zu <em>Merge-Konflikten<\/em> f\u00fchren kann, wenn bspw. zwei unterschiedliche \u00c4nderungen an ein und dem selben Abschnitt einer Datei vorgenommen wurden, was dann manuell aufgel\u00f6st werden muss.<\/p>\n<h2>Wie fange ich an?<\/h2>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Los-geht\u2019s-Git-Grundlagen\">RTFM<\/a><\/p>\n<h3>Hilfe<\/h3>\n<p><code>git help [&lt;Kommando&gt;]<\/code><\/p>\n<h3>Ein neues Repository erzeugen<\/h3>\n<p><code>git init &lt;verzeichnis&gt;<\/code><\/p>\n<p>Initialisiert ein neues Repo in <verzeichnis>, i.e. legt den Ordner <verzeichnis>\/.git an, in dem die Versionsdatenbank etc. liegt.<br \/>\nDas Verzeichnis muss nicht leer sein, so kann ein bestehendes Projekt leicht in die git Versionsverwaltung eingebunden werden.<br \/>\nEvtl. vorhandene Dateien (auch das Verzeichnis selbst) sind <em>noch nicht gestaget<\/em>! Am besten wird nach dem Initialisieren eine erste Version erzeugt:<br \/>\n<code>cd  &lt;verzeichnis&gt;<br \/>\ngit add .<br \/>\ngit commit -m 'Initial commit'<\/code><\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-Ein-Git-Repository-anlegen\">Git Buch &#8211; Ein Git-Repository anlegen<\/a><\/p>\n<h3>Ein Repository clonen<\/h3>\n<p>Will man stattdessen ein bereits existierendes Repo benutzen, \u2026<\/p>\n<p><code>git clone https:\/\/github.com\/AliTe\/experimini_20151021_git.git<\/code><\/p>\n<p>Erzeugt einen lokalen <em>Clone<\/em> des entsprechenden Repos auf GitHub.<\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-Ein-Git-Repository-anlegen#Ein-existierendes-Repository-klonen\">Git Buch &#8211; Eein existisrendes Repository klonen<\/a><\/p>\n<h3>\u00c4nderungen vornehmen<\/h3>\n<p>Nachdem alle \u00c4nderungen vorgenommen wurden, \u2026<\/p>\n<p><code>git add &lt;datei&gt;<\/code><\/p>\n<p>oder<\/p>\n<p><code>git add -A<\/code><\/p>\n<p>um alles zu stagen.<\/p>\n<p>Danach dann mit<\/p>\n<p><code>git commit<\/code><\/p>\n<p>alle gestageten \u00c4nderungen in Repo \u00fcbernehmen. Ein commit \u00f6ffnet in der Regel den Editor zum Verfassen der commit-Message; eine leere Meldung bricht den commit ab.<br \/>\nEs bew\u00e4hrt sich in der commit message in der ersten Zeile eine kurze Zusammenfassung der vorgenommenen \u00c4nderungen zu schreiben, dann eine Leerzeile und dann ggf. etwas ausf\u00fchrlicheren Text. Viele Tools zeigen in \u00dcbersichts-Ansichten dann nur die erste Zeile an und gew\u00e4hren so einen kompakten \u00dcberblick.<\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-\u00c4nderungen-am-Repository-nachverfolgen\">Git Buch &#8211; \u00c4nderungen am Repository nachverfolgen<\/a><\/p>\n<h3>Einen Branch anlegen<\/h3>\n<p>Um aktuell die Arbeit in einem neuen Branch zu beginnen bzw. fortzusetzen, nutzt man<br \/>\n<code>git checkout -b &lt;neuer Branchname&gt;<\/code><\/p>\n<p>Dies erzeugt einen neuen Branch und wechselt sofort in diesen.<br \/>\nEinen Branch erzeugen, ohnen ihn auch gleich auszuchecken geht mit:<br \/>\n<code>git branch &lt;neuer Branchname&gt;<\/code><\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Branching\">Git Buch &#8211; Git Branching<\/a><\/p>\n<h3>Arbeitsbereich updaten: Fetch und Pull<\/h3>\n<p>Vor der Arbeit an einem Projekt, an dem auch andere Team-Mitglieder arbeiten, empfiehlt es sich, Informationen \u00fcber von anderen vorgenommen \u00c4nderungen zu erneuern:<br \/>\n<code>git fetch [&lt;remote&gt;|--all]<\/code><\/p>\n<p>Bevor man die Arbeit an einem bestimmten Branch fortsetzt, holt man sich die jew. aktuellen \u00c4nderungen mit<br \/>\n<code>git pull<\/code><\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-Mit-externen-Repositorys-arbeiten\">Git Buch &#8211; Mit externen Repositorys arbeiten<\/a><\/p>\n<h3>Die History betrachten<\/h3>\n<p>Mit<br \/>\n<code>git log<\/code><\/p>\n<p>kann man sich die History &#8211; das Log \u00fcber die bisher vorgenommenen \u00c4nderungen &#8211; betrachten.<br \/>\nMit<br \/>\n<code>git status<\/code><\/p>\n<p>kann man sich Informationen \u00fcber den aktuellen Zustand des Arbeitsbereichs anzeigen lassen.<\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-\u00c4nderungen-am-Repository-nachverfolgen\">Git Buch &#8211; \u00c4nderungen am Repository nachverfolgen<\/a><\/p>\n<h3>Mergen<\/h3>\n<p>Habe ich die \u00c4nderungen in einem Arbeitsbranch abgeschlossen (i.e. gestaget und commitet), wechsle ich zur\u00fcck in meinen Ausgangsbranch und <em>merge<\/em> die \u00c4nderungen meines Arbeitsbranches:<br \/>\n<code>git checkout &lt;Ausgangsbranch&gt;<br \/>\ngit merge &lt;Arbeitsbranch&gt;<br \/>\ngit branch -d &lt;Arbeitsbranch&gt;<\/code><\/p>\n<p>Letzter Befehl l\u00f6scht  meinen Arbeitsbranch wieder.<\/p>\n<p>Gibt es keine parallelen \u00c4nderungen, findet ein <em>Fast Forward Merge<\/em> statt &#8211; d.h. nur der &#8220;HEAD-Zeiger&#8221; wird aktualisiert.<\/p>\n<p>Haben parallel \u00c4nderungen stattgefunden, wird ein 3-Wege-Merge angewendet, bei dem die \u00c4nderungen seit dem letzten gemeinsamen Vorfahren verschmolzen werden. Dies kann u.U. zu Konflikten f\u00fchren, die manuell aufgel\u00f6st werden m\u00fcssen.<\/p>\n<h3>\u00c4nderungen in ein Remote Repository pushen<\/h3>\n<p>Um meine \u00c4nderungen in ein Remote zu \u00fcbertragen, wird <em>gepusht<\/em>:<br \/>\n<code>git push &lt;remote&gt; &lt;Branchname&gt;<\/code><\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-Mit-externen-Repositorys-arbeiten#\u00c4nderungen-in-ein-Remote-Repository-hochladen\">Git Buch &#8211; \u00c4nderungen in ein Remote Repository hochladen<\/a><\/p>\n<h3>Taggen<\/h3>\n<p>Jeder Snapshot eines Repos wird mit einer (md5) Hashsumme versehen und ist auf diese Weise referenzierbar.<br \/>\nM\u00f6chte man einen Snapshot explizit markieren (z.B. ein Milestone des Projektes, eine Release-Nummer o.\u00e4.) kann man dazu einen <em>Tag<\/em> setzen:<br \/>\n<code>git tag &lt;tagname&gt;<\/code><\/p>\n<p><em>Tags<\/em> k\u00f6nnen auch auf ein Remote gepusht werden. Zudem ist es m\u00f6glich ein Tag mit seinem PGP\/GPG Key zu signieren.<\/p>\n<p><a href=\"http:\/\/git-scm.com\/book\/de\/v1\/Git-Grundlagen-Tags\">Git Buch &#8211; Tags<\/a><\/p>\n<h3>Praktische Tools und Tipps<\/h3>\n<ul>\n<li>.gitignore \/ .gitkeep<\/li>\n<li>.gitconfig lokal\/global<\/li>\n<li>Submodules \/ Subtrees<\/li>\n<\/ul>\n<h2>Weiterf\u00fchrende Techniken \/ Konzepte<\/h2>\n<ul>\n<li>Gitflow<\/li>\n<li>GitHub\/GitLab\/Bitbucket<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Was ist GIT? Git ist eine Sammlung von Werkzeugen zur Versionsverwaltung von Dateien. Im Laufe der Arbeit an Dateien (z.B. Programm-Code) kann damit jeder Entwicklungsstand eines Projektes festgehalten werden. Es kann (fast) nichts verloren gehen &#8211; Snapshot, History Es k\u00f6nnen nebeneinander verschiedene Versionen eines Projekts gepflegt werden (man m\u00f6chte bspw. etwas ausprobieren, was sp\u00e4ter gegebenenfalls &hellip; <a href=\"https:\/\/www.experimini.org\/blog\/?page_id=269\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">GIT Versionsverwaltung<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":20,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-269","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=269"}],"version-history":[{"count":1,"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/269\/revisions"}],"predecessor-version":[{"id":270,"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/269\/revisions\/270"}],"up":[{"embeddable":true,"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=\/wp\/v2\/pages\/20"}],"wp:attachment":[{"href":"https:\/\/www.experimini.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}