Git Grundbefehle

Aus Thomas-Krenn-Wiki
Wechseln zu: Navigation, Suche

Im folgenden Artikel werden die wichtigsten Git-Befehle erklärt, die bei der täglichen Arbeit mit dem verteilten Versionierungssystem hilfreich sind. Es wird darauf eingegangen wie mit der Working Copy Änderungen commited, rückgängig gemacht, mit anderen Versionen verglichen oder zusammengeführt werden. Voraussetzung für das Arbeiten mit Git, ist ein Grundverständnis der Begriffe im Zusammenhang mit Repositories. Diese finden sich z.B. im Artikel Git Grundbegriffe oder im Git Community Book wieder. Einen kompakten Überblick über die wichtigsten Git-Befehle bietet auch das git-cheat-sheet.

Die hier angeführten Beispiele wurden auf einem Ubuntu 11.10 ausgeführt und getestet. Auf diesem System wurde außerdem das Paket git-doc installiert, wodurch ein Git-Tutorial mittels "man gittutorial" zur Verfügung steht.

Konfiguration von User- und E-Mail-Informationen

Git gibt bei jedem Commit (einspielen von Änderungen ins Repo) den Namen und die Email-Adresse des Committers mit an. Bevor Git zum Einsatz kommt, werden diese Werte gesetzt und überprüft:

git config --global user.name "Test User"
git config --global user.email "tktest@example.com"
git config --global core.editor "vim"

Diese Angaben sind global gültig und gelten somit für alle Repos. Die Config wird ein weiteres Mal einem Check unterzogen:

:~$ git config --global -l
user.name=Test User
user.email=tktest@example.com

Eine weitere nützliche Konfiguration, bevor ein Repo in einem Verzeichnis erstellt wird, ist das Ignorieren von Dateien. Jene Dateien, die nicht versioniert werden sollen, kommen in die Datei ".gitignore". Diese Einstellung macht z.B. Sinn für Verzeichnisse, die kompilierte Binaries enthalten (z.B. Verzeichnis "bin"):

echo bin >> .gitignore

Grundlegende Arbeiten im Git Repo

Angenommen im Verzeichnis "project" befinden sich bereits Dateien, die versioniert werden sollen. Dazu wird Git in diesem Verzeichnis aufgerufen:

:~/Repos/project$ git init
Initialized empty Git repository in /home/tktest/Repos/project/.git/

Bis jetzt befinden sich noch keine Dateien unter Versionskontrolle. Für die vorhandene Datei "main.c" wird dies nun geändert:

:~/Repos/project$ git add main.c
:~/Repos/project$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#	new file:   main.c
#
:~/Repos/project$ git commit -m "Neue Main-Datei erstellt"
[master (root-commit) ce004cb] Neue Main-Datei erstellt
 1 files changed, 6 insertions(+), 0 deletions(-)
 create mode 100644 main.c

Mittels commit wird die Datei "main.c" ins Repo gespielt. Wird diese Datei bearbeitet, werden die Änderungen protokolliert und können bearbeitet werden (commit, revert etc.). Testweise wird eine neue Zeile eingefügt und mittels "git diff" begutachtet:

:~/Repos/project$ git diff main.c
diff --git a/main.c b/main.c
index b424dc0..678e613 100644
--- a/main.c
+++ b/main.c
@@ -2,5 +2,6 @@
 
 int main(void){
        printf("Hello World...\n");
+       int i = 42;
        return 0;
 }

Der Status zeigt weiters, dass eine Datei editiert wurde:

:~/Repos/project$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   main.c
#
no changes added to commit (use "git add" and/or "git commit -a")

Auch diese Zeile wird wieder ins Repos gespielt:

:~/Repos/project$ git commit -a -m "Zeile mit Integer Wert"
[master 58d507f] Zeile mit Integer Wert
 1 files changed, 1 insertions(+), 0 deletions(-)

Das Git Log zeigt auch schon die beiden Commits:

:~/Repos/project$ git log
commit 58d507f3b1ede925708bce7b6e443da296285f3c
Author: Test User <tktest@example.com>
Date:   Wed Jan 18 10:36:54 2012 +0100

    Zeile mit Integer Wert

commit ce004cbff963c582e381c074f64790dd908db76b
Author: Test User <tktest@example.com>
Date:   Wed Jan 18 10:28:57 2012 +0100

    Neue Main-Datei erstellt

Als Nächstes wird eine einfache Funktion erstellt:

:~/Repos/project$ git diff main.c
diff --git a/main.c b/main.c
index 678e613..fa55f09 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,12 @@
 #include <stdio.h>
 
+void help(void){
+       printf("This is a simple help message...\n");
+}
+
 int main(void){
        printf("Hello World...\n");
        int i = 42;
+       help();
        return 0;
 }

Diese Änderung kann wie folgt wieder verworfen werden:

:~/Repos/project$ git checkout -- main.c
:~/Repos/project$ git diff main.c

Sollen bereits ins Repos gespielte Änderungen wieder rückgängig gemacht werden, kann dies über ein Revert durchgeführt werden. Beim dem aktuellsten Commit stellt dies kein Problem dar, bei früheren Commits die sich evtl. gegenseitig Überlappen, müssen Konflikte manuell editiert werden (vgl. einem Merge). Der letzte Commit wird somit rückgängig gemacht und führt automatisch zu einem neuen Commit:

:~/Repos/project$ git revert HEAD 
[master 1f8bc85] Revert "Added commet to print"
 1 files changed, 0 insertions(+), 1 deletions(-)

Mittels git show wird der letzte Eintrag im Repo begutachtet:

:~/Repos/project$ git show
commit 1f8bc856da19c40b9f3eb01e4415c870a19afcd8
Author: Test User <tktest@example.com>
Date:   Wed Jan 18 11:30:40 2012 +0100

    Revert "Added commet to print"
    
    This reverts commit 63d4297d98b1c0eaddde11b902268fa4e4de9c3c.

diff --git a/main.c b/main.c
index 4b4121d..678e613 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,6 @@
 #include <stdio.h>
 
 int main(void){
-       //print out hello world
        printf("Hello World...\n");
        int i = 42;
        return 0;

Weitere nützliche Befehle

Kürzere Commit-Hashes

Für einige Befehle in Git werden die SHA1 Hashes von Commits benötigt, allerdings sind diese Hashes sehr lang und umständlich zu verwenden. Es gibt aber eine Möglichkeit die Handhabung zumindest zu vereinfachen. Git benötigt nicht unbedingt den kompletten Hash, sondern kann auch nur mit den ersten Stellen des Hashes (wenn eindeutig) arbeiten. Als Hilfsmittel um solche eindeutigen, kurzen Hashes zu erhalten kann git log folgendermaßen verwendet werden.

git log --abbrev-commit

Dadurch wählt Git automatisch die richtige Länge (min. 7 Stellen) um eindeutige, möglichst kurze Hashes zu erhalten. Diese können dann in allen Git Kommandos, die mit Hashes arbeiten, statt den kompletten SHA1 Hashes verwendet werden.

Bestimmte Version einer Datei wiederherstellen

Manchmal kann es notwendig sein nicht nur die letzte Version einer Datei wiederherzustellen, sondern eine Version die schon länger zurückliegt. Zuerst muss der entsprechende SHA Hash der wiederherzustellenden Version bekannt sein, man kann diesen z.B. mithilfe von git log und git diff herausfinden. Ist dieser bekannt kann die Version folgendermaßen wiederhergestellt werden.

git checkout <Hash> <filename>

Es gibt noch eine einfachere Möglichkeit um Versionen relativ zu einer anderen wiederherzustellen.

git checkout <Hash>~n <filename>

n ist die Anzahl an Versionen vor jener, deren Hash angegeben wurde. Zur Verdeutlichung ein weiteres Beispiel:

git checkout master~1 <filename>

Dieser Befehl stellt den Commit vor dem letzten Commit in master wieder her.

Änderungen zwischen zwei bestimmten Versionen

Wenn man sehen will was sich zwischen zwei Versionen geändert hat, kann man sich dies folgendermaßen anzeigen lassen.

git diff <Hash1>..<Hash2>

Achtung: Angezeigt werden auch alle Änderungen zwischen diesen beiden Versionen

Bestimmte Version anzeigen

Um Informationen zu einer bestimmten Version zu erhalten kann git show folgendermaßen verwendet werden.

git show <Hash>

Dieser Befehl zeig folgende Informationen zu dem ausgewählten Commit an:

  • Commit Datum
  • Autor
  • Parent
  • Diff aller geänderten Dateien

Wenn nur ein bestimmtes File betrachtet werden soll:

git show <Hash>:<filename>

Wer hat Was, Wann, Wo geändert ?

Wenn man wissen will welche Änderungen, von wem, in welcher Version, in einem bestimmten File vorgenommen wurden, kann man dafür git blame verwenden.

git blame <filename>

Dieser Befehl zeigt zu jeder Zeile im File wer diese in welcher Version geändert hat.

Lokale und Remote Branch vergleichen

Bevor man ein git pull durchführt, kann es sinnvoll sein, zu prüfen, was sich tatsächlich geändert hat durch den Vergleich der lokalen und der remote Branch.

git fetch .
git diff master origin/master

Übernommen können die Änderungen dann via git pull werden.

Git Branches

Ein Branch ist ein eigener Entwicklungszweig, der z.B. dazu dient um ein neues Feature zu entwickeln, zu testen und erst dann in den Master-Zweig zu übernehmen, wenn die Komponente fertig gestellt wurde. Auch Änderungen von anderen Entwicklern, die zuerst begutachtet werden sollen, bearbeitet man idealerweise in einem separaten Branch.[1] Im folgenden Beispiel wird ein Branch erstellt, um eine neue Funktion im File "main.c" hinzuzufügen. Zunächst werden alle vorhandenen Branches ausgegeben:

:~/Repos/project$ git branch
* master

Der master-Branch ist der Default-Branch, der automatisch beim Anlegen des Repos erstellt wurde. Dazu kommt nun der neue Branch "function":

:~/Repos/project$ git branch function
:~/Repos/project$ git branch 
  function
* master
:~/Repos/project$ git checkout function
Switched to branch 'function'

Im function-Branch wird eine neue Funktion hinzugefügt und getestet. Abschließend wird der function-Branch in den master-Branch zurück gemerged.

:~/Repos/project$ git status
# On branch function
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   main.c
#
:~/Repos/project$ git commit -a -m "added help function"
[function c1b6fa4] added help function
 1 files changed, 7 insertions(+), 0 deletions(-)
:~/Repos/project$ git checkout master
Switched to branch 'master'
:~/Repos/project$ git status
# On branch master
nothing to commit (working directory clean)
:~/Repos/project$ cat main.c 
#include <stdio.h>

int main(void){
	printf("Hello World...\n");
	int i = 42;
	return 0;
}

Die Änderungen aus dem function-Branch kommen in den master-Branch zurück:

:~/Repos/project$ git merge function
Updating 1f8bc85..c1b6fa4
Fast-forward
 main.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

Git show zeigt wiederum die letzten Änderungen:

:~/Repos/project$ git show main.c
commit c1b6fa4a907f4413ea18ad5f3bdc6a1717fe1371
Author: Test User <tktest@example.com>
Date:   Wed Jan 18 12:56:20 2012 +0100

    added help function

diff --git a/main.c b/main.c
index 678e613..7bc02a2 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,14 @@
 #include <stdio.h>
 
+void help(void){
+       printf("a simple help message\n");
+       return 0;
+}
+
+
 int main(void){
        printf("Hello World...\n");
        int i = 42;
+       help();
        return 0;
 }

Weitere Informationen zu Branches finden Sie im Artikel Git Branches.

Einzelnachweise

  1. Git User Manual - What is a branch (schacon.github.com)

Das könnte Sie auch interessieren

Etc-Verzeichnis mit etckeeper versionieren
Git Server-Konfiguration
Git Workflows