English ▾ Themen ▾ Neueste Version ▾ gittutorial zuletzt aktualisiert in 2.46.1

NAME

gittutorial - Eine Einführung in Git

SYNOPSIS

git *

BESCHREIBUNG

Dieses Tutorial erklärt, wie man ein neues Projekt in Git importiert, Änderungen daran vornimmt und Änderungen mit anderen Entwicklern teilt.

Wenn Sie stattdessen hauptsächlich daran interessiert sind, Git zum Abrufen eines Projekts zu verwenden, um beispielsweise die neueste Version zu testen, sollten Sie vielleicht mit den ersten beiden Kapiteln von Das Git User Manual beginnen.

Beachten Sie zunächst, dass Sie die Dokumentation für einen Befehl wie git log --graph mit

$ man git-log

oder

$ git help log

Mit letzterem können Sie den manuellen Betrachter Ihrer Wahl verwenden; weitere Informationen finden Sie unter git-help[1].

Es ist ratsam, sich mit Ihrem Namen und Ihrer öffentlichen E-Mail-Adresse mit Git vertraut zu machen, bevor Sie eine Operation durchführen. Der einfachste Weg, dies zu tun, ist

$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com

Importieren eines neuen Projekts

Angenommen, Sie haben ein Tarball project.tar.gz mit Ihrer ursprünglichen Arbeit. Sie können es wie folgt unter Git-Revisionskontrolle stellen.

$ tar xzf project.tar.gz
$ cd project
$ git init

Git wird antworten

Initialized empty Git repository in .git/

Sie haben nun das Arbeitsverzeichnis initialisiert – Sie bemerken vielleicht ein neues Verzeichnis namens .git.

Sagen Sie Git als Nächstes, dass es einen Snapshot des Inhalts aller Dateien im aktuellen Verzeichnis (beachten Sie den .) mit git add erfassen soll.

$ git add .

Dieser Snapshot wird nun in einem temporären Staging-Bereich gespeichert, den Git als "Index" bezeichnet. Sie können den Inhalt des Index dauerhaft im Repository speichern mit git commit.

$ git commit

Dies fordert Sie zur Eingabe einer Commit-Nachricht auf. Sie haben nun die erste Version Ihres Projekts in Git gespeichert.

Änderungen vornehmen

Ändern Sie einige Dateien und fügen Sie dann ihre aktualisierten Inhalte zum Index hinzu.

$ git add file1 file2 file3

Sie sind nun bereit zum Commit. Sie können sehen, was zum Commit ansteht, indem Sie git diff mit der Option --cached verwenden.

$ git diff --cached

(Ohne --cached zeigt git diff Ihnen alle Änderungen an, die Sie vorgenommen, aber noch nicht zum Index hinzugefügt haben.) Sie können auch eine kurze Zusammenfassung der Situation mit git status erhalten.

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

	modified:   file1
	modified:   file2
	modified:   file3

Wenn Sie weitere Anpassungen vornehmen müssen, tun Sie dies jetzt und fügen Sie dann alle neu geänderten Inhalte zum Index hinzu. Schließlich committen Sie Ihre Änderungen mit

$ git commit

Dies fordert Sie erneut zur Eingabe einer Nachricht auf, die die Änderung beschreibt, und zeichnet dann eine neue Version des Projekts auf.

Alternativ können Sie anstelle des vorherigen Aufrufs von git add verwenden

$ git commit -a

Dies bemerkt automatisch alle geänderten (aber nicht neuen) Dateien, fügt sie zum Index hinzu und committet sie in einem Schritt.

Hinweis zu Commit-Nachrichten: Obwohl nicht erforderlich, ist es eine gute Idee, die Commit-Nachricht mit einer einzigen kurzen (nicht mehr als 50 Zeichen) Zeile zu beginnen, die die Änderung zusammenfasst, gefolgt von einer Leerzeile und dann einer ausführlicheren Beschreibung. Der Text bis zur ersten Leerzeile in einer Commit-Nachricht wird als Commit-Titel behandelt, und dieser Titel wird in ganz Git verwendet. Zum Beispiel wandelt git-format-patch[1] einen Commit in eine E-Mail um und verwendet den Titel in der Betreffzeile und den Rest des Commits im Körper.

Git verfolgt Inhalte, nicht Dateien

Viele Versionskontrollsysteme bieten einen Befehl add, der dem System mitteilt, die Verfolgung von Änderungen an einer neuen Datei zu beginnen. Der add-Befehl von Git tut etwas Einfacheres und Mächtigeres: git add wird sowohl für neue als auch für neu geänderte Dateien verwendet, und in beiden Fällen wird ein Snapshot der angegebenen Dateien erstellt und dieser Inhalt im Index bereitgestellt, bereit für die Aufnahme in den nächsten Commit.

Projektverlauf anzeigen

Sie können jederzeit den Verlauf Ihrer Änderungen anzeigen mit

$ git log

Wenn Sie auch vollständige Diffs bei jedem Schritt sehen möchten, verwenden Sie

$ git log -p

Oft ist die Übersicht über die Änderung nützlich, um ein Gefühl für jeden Schritt zu bekommen.

$ git log --stat --summary

Branches verwalten

Ein einzelnes Git-Repository kann mehrere Entwicklungszweige (Branches) pflegen. Um einen neuen Branch namens experimental zu erstellen, verwenden Sie

$ git branch experimental

Wenn Sie jetzt ausführen

$ git branch

erhalten Sie eine Liste aller vorhandenen Branches.

  experimental
* master

Der Branch experimental ist der, den Sie gerade erstellt haben, und der Branch master ist ein Standard-Branch, der automatisch für Sie erstellt wurde. Der Stern markiert den Branch, auf dem Sie sich gerade befinden; tippen Sie

$ git switch experimental

um zum Branch experimental zu wechseln. Bearbeiten Sie nun eine Datei, committen Sie die Änderung und wechseln Sie zurück zum Branch master.

(edit file)
$ git commit -a
$ git switch master

Prüfen Sie, ob die von Ihnen vorgenommene Änderung nicht mehr sichtbar ist, da sie im Branch experimental vorgenommen wurde und Sie sich wieder im Branch master befinden.

Sie können eine andere Änderung im Branch master vornehmen.

(edit file)
$ git commit -a

An diesem Punkt haben sich die beiden Branches verzweigt, wobei in jedem unterschiedliche Änderungen vorgenommen wurden. Um die im Branch experimental vorgenommenen Änderungen in master zusammenzuführen, führen Sie aus

$ git merge experimental

Wenn die Änderungen nicht kollidieren, sind Sie fertig. Wenn es Konflikte gibt, werden Markierungen in den problematischen Dateien hinterlassen, die den Konflikt anzeigen;.

$ git diff

zeigt dies. Sobald Sie die Dateien bearbeitet haben, um die Konflikte zu lösen,

$ git commit -a

committet das Ergebnis des Merges. Schließlich,

$ gitk

zeigt eine schöne grafische Darstellung des daraus resultierenden Verlaufs.

An diesem Punkt könnten Sie den Branch experimental löschen mit

$ git branch -d experimental

Dieser Befehl stellt sicher, dass die Änderungen im Branch experimental bereits im aktuellen Branch vorhanden sind.

Wenn Sie in einem Branch crazy-idea entwickeln und es dann bereuen, können Sie den Branch immer mit

$ git branch -D crazy-idea

löschen. Branches sind billig und einfach, daher ist dies eine gute Möglichkeit, etwas auszuprobieren.

Git für die Zusammenarbeit nutzen

Angenommen, Alice hat ein neues Projekt mit einem Git-Repository in /home/alice/project gestartet und Bob, der ein Home-Verzeichnis auf demselben Rechner hat, möchte beitragen.

Bob beginnt mit

bob$ git clone /home/alice/project myrepo

Dies erstellt ein neues Verzeichnis myrepo, das eine Kopie von Alices Repository enthält. Die Kopie steht dem Originalprojekt gleichberechtigt gegenüber und verfügt über eine eigene Kopie des Verlaufs des Originalprojekts.

Bob nimmt dann einige Änderungen vor und committet sie.

(edit files)
bob$ git commit -a
(repeat as necessary)

Wenn er bereit ist, weist er Alice an, Änderungen aus dem Repository unter /home/bob/myrepo zu ziehen. Sie tut dies mit

alice$ cd /home/alice/project
alice$ git pull /home/bob/myrepo master

Dies führt die Änderungen von Bobs master-Branch in Alices aktuellen Branch zusammen. Wenn Alice inzwischen eigene Änderungen vorgenommen hat, muss sie möglicherweise Konflikte manuell beheben.

Der Befehl pull führt also zwei Operationen aus: Er holt Änderungen von einem entfernten Branch und führt sie dann in den aktuellen Branch zusammen.

Beachten Sie, dass Alice im Allgemeinen ihre lokalen Änderungen committen möchte, bevor sie diesen pull initiiert. Wenn Bobs Arbeit mit dem kollidiert, was Alice seit der Abzweigung ihrer Verläufe getan hat, wird Alice ihren Arbeitsbaum und den Index verwenden, um Konflikte zu lösen, und bestehende lokale Änderungen werden den Konfliktlösungsprozess stören (Git wird den Fetch trotzdem durchführen, aber das Merging verweigern – Alice muss ihre lokalen Änderungen irgendwie beseitigen und erneut pullen, wenn dies passiert).

Alice kann einen Blick darauf werfen, was Bob getan hat, ohne zuerst zu mergen, indem sie den Befehl fetch verwendet; dies ermöglicht Alice, zu inspizieren, was Bob getan hat, unter Verwendung eines speziellen Symbols FETCH_HEAD, um festzustellen, ob er etwas Wertvolles zum Ziehen hat, wie folgt:

alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD

Diese Operation ist sicher, auch wenn Alice uncommittete lokale Änderungen hat. Die Bereichsnotation HEAD..FETCH_HEAD bedeutet "zeige alles, was von FETCH_HEAD erreichbar ist, aber schließe alles aus, was von HEAD erreichbar ist". Alice kennt bereits alles, was zu ihrem aktuellen Zustand (HEAD) führt, und überprüft mit diesem Befehl, was Bob in seinem Zustand (FETCH_HEAD) hat, das sie noch nicht gesehen hat.

Wenn Alice visualisieren möchte, was Bob getan hat, seit ihre Verläufe sich verzweigt haben, kann sie den folgenden Befehl ausführen:

$ gitk HEAD..FETCH_HEAD

Dies verwendet die gleiche Zwei-Punkt-Bereichsnotation, die wir bereits mit git log gesehen haben.

Alice möchte vielleicht sehen, was beide getan haben, seit sie sich verzweigt haben. Sie kann die Drei-Punkt-Form anstelle der Zwei-Punkt-Form verwenden.

$ gitk HEAD...FETCH_HEAD

Das bedeutet: "Zeige alles, was von einem der beiden erreichbar ist, aber schließe alles aus, was von beiden erreichbar ist."

Bitte beachten Sie, dass diese Bereichsnotationen sowohl mit gitk als auch mit git log verwendet werden können.

Nachdem sie Bobs Arbeit inspiziert hat, und wenn nichts dringend ist, kann Alice entscheiden, weiterzuarbeiten, ohne von Bob zu pullen. Wenn Bobs Verlauf etwas enthält, das Alice sofort benötigen würde, kann Alice ihre laufende Arbeit zuerst "stasen", einen pull durchführen und dann ihre laufende Arbeit auf den resultierenden Verlauf "unstasen".

Wenn Sie in einer kleinen, eng verbundenen Gruppe arbeiten, ist es nicht ungewöhnlich, immer wieder mit demselben Repository zu interagieren. Durch die Definition von Remote-Repository-Kurznamen können Sie dies erleichtern.

alice$ git remote add bob /home/bob/myrepo

Damit kann Alice den ersten Teil der pull-Operation allein mit dem Befehl git fetch durchführen, ohne die Änderungen mit ihrem eigenen Branch zusammenzuführen, indem sie verwendet:

alice$ git fetch bob

Im Gegensatz zur Langform wird beim Abrufen von Bob mithilfe eines mit git remote eingerichteten Remote-Repository-Kurznamens das Abgerufene in einem Remote-Tracking-Branch gespeichert, in diesem Fall bob/master. Nach diesem Schritt also:

alice$ git log -p master..bob/master

zeigt eine Liste aller Änderungen, die Bob vorgenommen hat, seit er von Alices master-Branch abgezweigt ist.

Nachdem sie diese Änderungen geprüft hat, könnte Alice die Änderungen in ihren master-Branch zusammenführen.

alice$ git merge bob/master

Dieses merge kann auch durch Pullen vom eigenen Remote-Tracking-Branch erfolgen, wie folgt:

alice$ git pull . remotes/bob/master

Beachten Sie, dass git pull immer in den aktuellen Branch zusammenführt, unabhängig davon, was sonst noch auf der Befehlszeile angegeben wird.

Später kann Bob sein Repo mit Alices neuesten Änderungen aktualisieren mit

bob$ git pull

Beachten Sie, dass er den Pfad zu Alices Repository nicht angeben muss; als Bob Alices Repository klonte, speicherte Git den Speicherort ihres Repositorys in der Repository-Konfiguration, und dieser Speicherort wird für Pulls verwendet.

bob$ git config --get remote.origin.url
/home/alice/project

(Die vollständige Konfiguration, die von git clone erstellt wurde, ist mit git config -l sichtbar, und die Manpage git-config[1] erklärt die Bedeutung jeder Option.)

Git behält auch eine unveränderte Kopie von Alices master-Branch unter dem Namen origin/master.

bob$ git branch -r
  origin/master

Wenn Bob später beschließt, von einem anderen Host aus zu arbeiten, kann er immer noch Klone und Pulls mit dem SSH-Protokoll durchführen.

bob$ git clone alice.org:/home/alice/project myrepo

Alternativ hat Git ein natives Protokoll oder kann HTTP verwenden; siehe git-pull[1] für Details.

Git kann auch in einem CVS-ähnlichen Modus verwendet werden, mit einem zentralen Repository, zu dem verschiedene Benutzer Änderungen pushen können; siehe git-push[1] und gitcvs-migration[7].

Verlauf erkunden

Der Git-Verlauf wird als eine Reihe von zusammenhängenden Commits dargestellt. Wir haben bereits gesehen, dass der Befehl git log diese Commits auflisten kann. Beachten Sie, dass die erste Zeile jeder git log-Eintrag auch einen Namen für den Commit liefert.

$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date:   Tue May 16 17:18:22 2006 -0700

    merge-base: Clarify the comments on post processing.

Wir können diesen Namen an git show übergeben, um die Details dieses Commits anzuzeigen.

$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7

Aber es gibt auch andere Möglichkeiten, Commits zu referenzieren. Sie können jeden anfänglichen Teil des Namens verwenden, der lang genug ist, um den Commit eindeutig zu identifizieren.

$ git show c82a22c39c	# the first few characters of the name are
			# usually enough
$ git show HEAD		# the tip of the current branch
$ git show experimental	# the tip of the "experimental" branch

Jeder Commit hat normalerweise einen "Eltern"-Commit, der auf den vorherigen Zustand des Projekts verweist.

$ git show HEAD^  # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD

Beachten Sie, dass Merge-Commits mehr als einen Elternteil haben können.

$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD

Sie können Commits auch eigene Namen geben; nach dem Ausführen

$ git tag v2.5 1b2e1d63ff

können Sie 1b2e1d63ff unter dem Namen v2.5 referenzieren. Wenn Sie diesen Namen mit anderen Personen teilen möchten (z. B. um eine Release-Version zu identifizieren), sollten Sie ein "Tag"-Objekt erstellen und es vielleicht signieren; siehe git-tag[1] für Details.

Jeder Git-Befehl, der einen Commit kennen muss, kann einen dieser Namen annehmen. Zum Beispiel:

$ git diff v2.5 HEAD	 # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
			 # at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
			 # directory to its state at HEAD^

Seien Sie vorsichtig mit diesem letzten Befehl: Zusätzlich zum Verlust von Änderungen im Arbeitsverzeichnis werden auch alle späteren Commits aus diesem Branch entfernt. Wenn dieser Branch der einzige ist, der diese Commits enthält, gehen sie verloren. Verwenden Sie auch nicht git reset für einen öffentlich sichtbaren Branch, von dem andere Entwickler pullen, da dies unnötige Merges für andere Entwickler erzwingt, um den Verlauf zu bereinigen. Wenn Sie Änderungen rückgängig machen müssen, die Sie gepusht haben, verwenden Sie stattdessen git revert.

Der Befehl git grep kann nach Zeichenfolgen in jeder Version Ihres Projekts suchen, also:

$ git grep "hello" v2.5

sucht nach allen Vorkommen von "hello" in v2.5.

Wenn Sie den Commit-Namen weglassen, sucht git grep in allen Dateien, die es in Ihrem aktuellen Verzeichnis verwaltet. Also:

$ git grep "hello"

ist eine schnelle Möglichkeit, nur die von Git verfolgten Dateien zu durchsuchen.

Viele Git-Befehle akzeptieren auch Mengen von Commits, die auf verschiedene Weise angegeben werden können. Hier sind einige Beispiele mit git log.

$ git log v2.5..v2.6            # commits between v2.5 and v2.6
$ git log v2.5..                # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile       # commits since v2.5 which modify
				# Makefile

Sie können git log auch einen "Bereich" von Commits geben, wobei der erste nicht unbedingt ein Vorfahre des zweiten sein muss; wenn sich beispielsweise die Spitzen der Branches stable und master vor einiger Zeit von einem gemeinsamen Commit verzweigt haben, dann:

$ git log stable..master

listet Commits auf, die im Branch master vorgenommen wurden, aber nicht im stabilen Branch, während:

$ git log master..stable

zeigt die Liste der Commits an, die im stabilen Branch vorgenommen wurden, aber nicht im master-Branch.

Der Befehl git log hat eine Schwäche: Er muss Commits in einer Liste präsentieren. Wenn der Verlauf Entwicklungslinien hat, die sich verzweigt und dann wieder zusammengeführt haben, ist die Reihenfolge, in der git log diese Commits präsentiert, bedeutungslos.

Die meisten Projekte mit mehreren Mitwirkenden (wie der Linux-Kernel oder Git selbst) haben häufig Merges, und gitk leistet eine bessere Arbeit bei der Visualisierung ihres Verlaufs. Zum Beispiel:

$ gitk --since="2 weeks ago" drivers/

ermöglicht es Ihnen, alle Commits der letzten 2 Wochen zu durchsuchen, die Dateien im Verzeichnis drivers geändert haben. (Hinweis: Sie können die Schriftarten von gitk anpassen, indem Sie die Strg-Taste gedrückt halten, während Sie "-" oder "+" drücken.)

Schließlich erlauben die meisten Befehle, die Dateinamen annehmen, optional, jedem Dateinamen einen Commit voranzustellen, um eine bestimmte Version der Datei anzugeben.

$ git diff v2.5:Makefile HEAD:Makefile.in

Sie können auch git show verwenden, um eine solche Datei anzuzeigen.

$ git show v2.5:Makefile

Nächste Schritte

Dieses Tutorial sollte ausreichen, um grundlegende verteilte Versionskontrolle für Ihre Projekte durchzuführen. Um jedoch die Tiefe und Leistungsfähigkeit von Git vollständig zu verstehen, müssen Sie zwei einfache Ideen verstehen, auf denen es basiert.

  • Die Objektdatenbank ist das eher elegante System zur Speicherung des Verlaufs Ihres Projekts – Dateien, Verzeichnisse und Commits.

  • Die Indexdatei ist ein Cache des Zustands eines Verzeichnisbaums, der zum Erstellen von Commits, zum Auschecken von Arbeitsverzeichnissen und zum Halten der verschiedenen Bäume verwendet wird, die an einem Merge beteiligt sind.

Teil zwei dieses Tutorials erklärt die Objektdatenbank, die Indexdatei und ein paar andere Kleinigkeiten, die Sie benötigen, um Git optimal zu nutzen. Sie finden es unter gittutorial-2[7].

Wenn Sie damit nicht sofort weitermachen möchten, sind hier ein paar andere Abschweifungen, die zu diesem Zeitpunkt interessant sein könnten:

  • git-format-patch[1], git-am[1]: Diese konvertieren Serien von Git-Commits in E-Mail-Patches und umgekehrt, nützlich für Projekte wie den Linux-Kernel, die stark auf E-Mail-Patches angewiesen sind.

  • git-bisect[1]: Wenn es eine Regression in Ihrem Projekt gibt, ist eine Möglichkeit, den Fehler zu verfolgen, die Suche durch den Verlauf, um den genauen Commit zu finden, der dafür verantwortlich ist. git bisect kann Ihnen helfen, eine binäre Suche nach diesem Commit durchzuführen. Es ist intelligent genug, um eine nahezu optimale Suche durchzuführen, selbst im Falle eines komplexen nicht-linearen Verlaufs mit vielen zusammengeführten Branches.

  • gitworkflows[7]: Bietet einen Überblick über empfohlene Workflows.

  • giteveryday[7]: Alltägliches Git mit etwa 20 Befehlen.

  • gitcvs-migration[7]: Git für CVS-Benutzer.

GIT

Teil der git[1] Suite