1. t$ git init started...
Martin Schuhfuß
@usefulthink
2. about me…
Martin Schuhfuß
/ Hamburger (schon immer)
/ JS-Nerd, octocat-fanboy, Performance-Fetischist
/ verliebt in unmögliche Aufgaben und elegante Lösungen
/ Architekt und Entwickler bei spot-media AG (auch schon immer)
@usefulthink | github.com/usefulthink
3. und ihr so?
/ Arbeit mit größeren Teams?
/ Erfahrung mit Versionsmanagement?
/ …mit git?
/ …git auf der Kommandozeile?
9. ////////////////////////////////////////////////////////////////
! GIT - the stupid content tracker
////////////////////////////////////////////////////////////////
"git" can mean anything, depending on your mood.
- random three-letter combination that is pronounceable, and not
actually used by any common UNIX command. The fact that it is a
mispronunciation of "get" may or may not be relevant.
- stupid. contemptible and despicable. simple. Take your pick from the
dictionary of slang.
- "global information tracker": you're in a good mood, and it actually
works for you. Angels sing, and a light suddenly fills the room.
- "goddamn idiotic truckload of sh*t": when it breaks
Linus Torwalds, git README, initial commit
(https://github.com/git/git/blob/master/README)
10. New Oxford American Dictionary
Urban Dictionary
(http://www.urbandictionary.com/define.php?term=git)
11. „
git has taken over where Linux left off separating the geeks
into know-nothings and know-it-alls. I didn‘t really expect
anyone to use it because it‘s so hard to use, but that turns
out to be its big appeal.
No technology can ever be too arcane or complicated for the
black-t-shirt crowd.
Linus Torwalds in einem privaten Interview 2012
(http://typicalprogrammer.com?p=143)
13. Inhalt
/ Everyday git
/ Grundlagen und Hintergründe
I. Graphen und Erreichbarkeit
II. git-Objekte und Funktionsweise
/ Branches und Histories
14. ! Inhalt
/ Warum Git? (siehe http://whygitisbetterthanx.com/)
/ Umgang mit grafischen Tools und IDE-
Integration (ich bin bash-freund, seid es auch)
/ Viele, viele Varianten und mögliche
Parameter der Git-Befehle
17. config
git Konfigurieren
~/src/git-test $ git config --global user.name “Vor- und Nachname“
~/src/git-test $ git config --global user.email “someone@example.com“
~/src/git-test $ git config --global color.ui auto
(wird der Parameter --global weggelassen, wird die Konfiguration nur für das
aktuelle Repository angepasst)
Die globale Konfiguration von Git wird in der Datei ~/.gitconfig (ini-
Format) im Home-Verzeichnis gespeichert, lokale Konfiguration findet sich
im Projektverzeichnis unter .git/config
19. status
Änderungen und sonstige Status-Informationen des
Repositories abfragen.
...oder sich sagen lassen was zu tun ist :)
~/local/src/git-test $ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)
20. add
Änderungen in den Index aufnehmen und für den
nächsten Commit vorsehen.
~/src/git-test $ echo "Hallo Welt" > README.md
~/src/git-test $ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# README.md
nothing added to commit but untracked files present (use "git add" to track)
21. add
machen wir das doch einfach mal...
~/src/git-test $ git add README.md
~/src/git-test $ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: README.md
#
22. commit
neuen Snapshot erzeugen
~/src/git-test $ git commit -m 'first commit'
[master (root-commit) dc69a36] first commit
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 README.md
(-m: commit-message direkt angeben; andernfalls öffnet sich euer $EDITOR)
DISCLAIMER: Um mich kurzzufassen werde ich keine besonders hilfreichen
und/oder sinnvollen commit-messages schreiben. Normalerweise sterben
Kätzchen durch solche commit-messages.
23. weitere Änderungen
~/src/git-test $ 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: README.md
#
no changes added to commit (use "git add" and/or "git commit -a")
~/src/git-test $ git add README.md ; git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README.md
#
24. log und diff
Änderungen nachvollziehen
~/src/git-test $ git log
commit 2eee492f9f9941e18c0c1449dcfeb46c679ae080
Author: Martin Schuhfuss <m.schuhfuss@gmail>
Date: Fri Jan 6 15:57:59 2012 +0100
first comit
~/src/git-test $ echo "Hello World" > README.md
~/src/git-test $ git diff
diff --git a/README.md b/README.md
index b7d6715..557db03 100644
--- a/README.md
+++ b/README.md
@@ -1 +1 @@
-Hallo Welt
+Hello World
Die Befehle git log und git diff sind extrem vielseitig einsetzbar, abhängig
davon, mit welchen Parametern und Argumenten sie aufgerufen werden.
25. noch mehr...
weitere Befehle für den alltäglichen Gebrauch
git checkout <datei>: Änderungen rückgängig machen und
Datei im Arbeitsverzeichnis mit dem letzten Snapshot
überschreiben*.
git reset HEAD <datei>: Änderungen im Index / Staging-
Bereich rückgängig machen*.
git rm <datei>: Dateien löschen und aus dem Index
entfernen
* checkout und reset gehören mit zu den mächtigsten der git-Kommandos.
Hier beschrieben ist nur einer der einfachsten der Anwendungsfälle.
29. star-wars
Das Imperium Die Rückkehr Die dunkle Angriff der Die Rache
Krieg der Sterne Bedrohong Klonkrieger
schlägt zurück der Jedi-Ritter der Sith
1 2 3 4 5 6
= Nachfolger (Produktionsreihenfolge)
30. star-wars
Die dunkle Angriff der Die Rache Das Imperium Die Rückkehr
Bedrohong Klonkrieger Krieg der Sterne
der Sith schlägt zurück der Jedi-Ritter
4 5 6 1 2 3
= Nachfolger (Storyline)
31. AUCH ZEITLICHE ABFOLGE IST
star-wars
NICHT IMMER EINDEUTIG :)
DIE PRODUKTIONSREIHENFOLGE
MUSS NICHT ZWINGEND DIE
REIHENFOLGE SEIN, DIE SPÄTER
Die dunkle Angriff der Die Rache Das Imperium Die Rückkehr
Bedrohong Klonkrieger Krieg der Sterne
der Sith schlägt zurück der Jedi-Ritter
4 5 6 1 2 3
= Geschichte baut darauf auf
32. Revisions-Graph
Referenzen
nice_feature
Feature für neue
Version master
erste halbwegs endlich
beta d‘oh! neue Version
lauffähige Version gelauncht!
Das. Killer.
Feature.
awesomesauce
= wurde darauf aufgebaut
33. Revisions-Graph
Erreichbarkeit
Ist über keine
der Referenzen
zu erreichen! nice_feature
4
alter Feature für neue
kram Version master
1 2 3 5 6
erste halbwegs endlich
beta d‘oh! neue Version
lauffähige Version gelauncht!
7
Das. Killer.
Feature.
master 6–4–5–3–2–1
Die History sieht awesomesauce
nice_feature 4–2–1 für jede Referenz
anders aus
awesomesauce 7–5–3–2–1
34. Wozu das alles?
git wird niemals (wirklich nie)
irgendetwas löschen, was über eine
Referenz erreichbar ist.
(Ihr dürft euch jetzt entspannen.)
36. Snapshots
CVS/SVN Version 1 Version 2 Version 3 Version 4 Version 5
changes
(Deltas) File A Δ1 Δ2
over time
File B Δ1 Δ2
File C Δ1 Δ2 Δ3
Git Version 1 Version 2 Version 3 Version 4 Version 5
overall-state
(exact copy) A A1 A1 A2 A2
at a given
time
B B B B1 B2
C C1 C2 C2 C3
37. Git Objekte
5a9e02d9…
<?php
ef129a71… require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
Tree: fe32a871… use SymfonyComponentHttpFoundationRequest;
Parent: a9d81ef3… $kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
Author: Martin $kernel->handle(Request::createFromGlobals())->send();
Comitter: Martin
Awesome commit-message is Blob
awesome.
Commit fe32a871…
blob a501bc92… .htaccess
blob 5a9e02d9… app.php
blob 7e22a497… app_dev.php
tree 2149b94c… css
tree f02b2258… images
Tree
38. Git Objekte
~/src/git-test $ tree
.
!"" README.md
#"" web
!"" index.html
#"" style.css
~/src/git-test $ git add .
~/src/git-test $ git stat
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: web/index.html
# new file: web/style.css
#
~/src/git-test $ git commit -m ‘index and styles‘
[master 6434aeb] index and styles
1 files changed, 10 insertions(+), 0 deletions(-)
create mode 100644 web/index.html
create mode 100644 web/style.css
39. 2eee49… Git Objekte
initial commit
636af660…
97cd79d8…
Hallo Welt
blob 636af660… README.md
tree 6e6cee32… web
6434aeb7…
Tree: 97cd79d8…
Parent: 2eee492f… 94d985df…
index and styles <!DOCTYPE html>
<html>
<head>
6e6cee32… <title>Hallo Welt!</title>
<link rel="stylesheet" href="st…
</head>
<body>
blob 94d985df… index.html <h1>Hallo Welt!</h1>
</body>
blob e69de29b… style.css </html>
e69de29b…
<leer>
40. SHA1
e69de29b… 636af660…
<leer> Hallo Welt
Absolut und global Eindeutige Ids
Egal wo auf der Welt jemand eine leere Datei in einem git-repository
speichert – mit welchem Betriebssystem und welcher git-Version auch
immer – diese Datei wird immer denselben SHA1-Hash
(e69de29bb2d1d6434b8b29ae775ad8c2e48c5391) erhalten.
Aufgrund der tatsächlichen Länge der SHA1-Hashes (160 bit / 2160
mögliche Kombinationen) ist es faktisch ausgeschlossen, dass zwei
unterschiedliche Dateien mit denselben SHA1-Wert erhalten.
41. Three Trees
working HEAD
index
directory repository
Der aktuelle Checkout. Staging-Bereich zur Der HEAD-Commit
Dies ist das eigentliche Vorbereitung von zeigt auf den letzten
Projektverzeichnis und neuen Snapshots bzw. erzeugten Snapshot im
enthält die Dateien, mit Commits aktuellen Branch und
denen ihr arbeitet. ist immer der
Snapshot, der zum
Parent des nächsten
Commits wird.
42. Three Trees
git add <file ...>
git commit
git rm <file ...>
stage create
changes snapshot
working HEAD
index
directory repository
unstage
changes
git reset <file ...>
Die Dateien im Working
Directory bleiben unverändert,
die Änderungen werden aus
dem Index entfernt
43. Three Trees
Sowohl der Index als auch die
Working-Copy werden
zurückgesetzt
git reset --hard <file ...>
working HEAD
index
directory repository
unstage
changes
git reset <file ...>
Die Dateien im Working
Directory bleiben unverändert,
die Änderungen werden aus
dem Index entfernt
Unter dem Titel „reset demystified“ gibt auf progit.org (http://progit.org/2011/07/11/reset.html)
eine hervorragende Erklärung zu der genauen Funktionsweise von reset und checkout.
44. HEAD repository
master Beispiel
working HEAD
index
directory repository
45. HEAD repository
master
working HEAD
index
directory repository
README.md
Hallo Welt
echo “Hallo Welt“ > README.md
46. HEAD repository
master
636af6...
Hallo Welt
blob
working HEAD
index
directory repository
README.md README.md
636af6...
git add README.md
47. HEAD repository
master
2eee49... fd72bd... 636af6...
2eee49... Tree: fd72bd... blob 636af6... README.md Hallo Welt
Author: Martin
README.md: 636af6...
Comitter: Martin tree blob
initial commit
working commit
HEAD
index
directory repository
README.md README.md README.md
636af6... 636af6...
git commit -m ‘initial commit‘
48. HEAD repository
master
636af6...
2eee49... Hallo Welt
README.md: 636af6...
working HEAD
index
directory repository
README.md README.md README.md
Hello World!
Hallo Welt 636af6... 636af6...
jetzt ändern wir die README.md…
49. HEAD repository
master
7e5411… 636af6...
2eee49... Hello World! Hallo Welt
README.md: 636af6...
working HEAD
index
directory repository
README.md README.md README.md
Hello World! 7e5411…
636af6... 636af6...
git add README.md
50. HEAD repository
master
7e5411… 636af6...
2eee49... f6ba12... Hello World! Hallo Welt
README.md: 636af6... README.md: 7e5411...
working HEAD
index
directory repository
README.md README.md README.md
Hello World! 7e5411... 7e5411…
636af6...
git commit -m ‘english‘
52. Szenario
HEAD
…oder auch: der Commit,
HEAD der zum Parent von neuen
Commits wird
master
Branch
A B C eine Referenz für eine
Commit-Id
Commit
A, B, C usw. stehen als
Platzhalter für die
Verweis zum „echten“ Commit-Ids
Parent-Commit
Mit jedem Commit wird die Referenz (master) des aktuellen Branches (vom HEAD
angezeigt) automatisch mitbewegt.
53. Branch erstellen
master
A B C
feature
HEAD
Kurzform:
git checkout -b feature
git branch feature
git checkout feature
55. fast-forward merge
HEAD
master
A B C D
feature
mit git merge --no-ff feature
kann verhindert werden, dass fast- kein neuer commit
forward merges gemacht werden.
Bei einem fast-forward
Mit dem Parameter --ff-only
merge wird kein separater
werden sie erzwungen. merge-commit erzeugt,
lediglich der Ziel-Branch
git checkout master (master) wird auf die neue
Position „Vorgespult“.
git merge feature
56. Ein weiterer Commit
master
A B C D E
feature
HEAD
git checkout feature
git commit …
57. Bugfixes…
HEAD
master
F G
A B C D E
feature
git checkout master
git commit …
58. Merge!
Konflikte
...treten auf, wenn in beiden HEAD Commit-Message:
Branches in denselben Bereichen merged branch ‘feature‘
einer Datei Änderungen
vorgenommen wurden master
F G H
C D E
feature merge-commit
...hat im Gegensatz zu einem
normalen Commit zwei
Elternteile und wird aus den
Änderungen der beiden
Branches kombiniert.
git checkout master
git merge feature
59. Konflikte vermeiden
git rebase
master
F G D‘ E‘
C D E feature
ACHTUNG
nach dem rebase sind die HEAD
git rebase nimmt alle
Original-Commits nur noch
Änderungen aus einem
über ihre Id erreichbar.
bestehenden Branch und
verschiebt diese an eine
andere Position. Die Basis
(nearest common ancestor)
des feature-Branches
wird dabei von C zu G
git checkout feature
git rebase master
60. ups.
irgendwas schief gelaufen?
Komisches Zeug auf der Kommandozeile?
Irgendwas falsch gemacht?
61.
62. git wird niemals (wirklich nie)
irgendetwas löschen, was über eine
Referenz erreichbar ist.
(Ihr dürft euch jetzt auch wieder entspannen.)
63. Der Rückwärtsgang
--abort – Alles zurück auf Anfang
~/src/git-test $ $ git rebase master
First, rewinding head to replay your work on top of it...
Applying: first feature commit
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Failed to merge in the changes.
Patch failed at 0001 first feature commit
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
~/src/git-test $ git rebase --abort
64. Der Vorwärtsgang
rebase - Konflikte auflösen
~/src/git-test $ $ git rebase master
First, rewinding head to replay your work on top of it...
Applying: first feature commit
Using index info to reconstruct a base tree... Commit-Message des
Falling back to patching base and 3-way merge... fehlgeschlagenen patches
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Failed to merge in the changes.
Patch failed at 0001 first feature commit
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
65. Der Vorwärtsgang
rebase - Konflikte auflösen
~/src/git-test $ git stat
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: web/style.css
#
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: README.md Jeder Konflikt innerhalb der Datei
# wird mit Markierungen versehen.
~/src/git-test $ cat README.md Die Datei wird bearbeitet, und der
<<<<<<< HEAD Konflikt aufgelöst, wobei die
Hallo Welt! MArkierungen entfernt werden.
im branch master kommt was dazu...
=======
Hello World
>>>>>>> first feature commit
66. Der Vorwärtsgang
rebase - Konflikte auflösen
~/src/git-test $ cat README.md
Hello World
im branch master kommt was dazu...
~/src/git-test $ git add README.md
~/src/git-test $ git stat
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README.md
# modified: web/style.css
#
~/src/git-test $ git rebase --continue
Applying: first feature commit
Applying: second commit (add file)
Applying: third commit (changed README.md)
67. moar fun with rebase
feature-b HEAD
master N O feature-b
K L M N‘ O‘
feature-a
git rebase master feature-b --onto feature-a
from to new base
~/src/git-test $ git rebase master feature-b --onto feature-a
First, rewinding head to replay your work on top of it...
Applying: first commit on branch feature-b (N $ N‘)
Applying: second commit on branch feature-b (O $ O‘)
69. hilfreiche Befehle
git add --patch: interaktives Staging von Änderungen. Hilft,
wenn in einer Datei Änderungen sind, die getrennt
voneinander comitted werden sollen.
git commit --amend: den letzen Commit nochmal
bearbeiten. Üblicherweise zum Beheben von Tippfehlern in
Commit-Messages aber auch
git rebase --interactive: wie commit --amend auf Crack. Mit
Kettensäge*. Erlaubt das beliebige Umstellen und
nachträgliche Ändern von Commits. Unfassbar mächtig,
aber mit Vorsicht zu genießen (vorher immer ein Tag
setzen, dann kann man sich zumindest wieder retten,
wenns was nicht klappt).
70. hilfreiche Befehle
git stash und git stash pop: Mit git stash können alle gerade
vorhandenen Änderungen „beiseite gelegt“ werden. Das
Working-Directory und der Index werden auf den Stand des
HEAD zurückgesetzt. stash pop stellt den beiseite gelegten
Stand wieder her.
git clean: Räumt unversionierte Dateien aus dem Weg, mit
dem Parameter -f werden nur unversionierte Dateien
entfernt, mit -d auch die Verzeichnisse.
git mergetool: Die UNO oder sowas. Hilft bei der
Konfliktlösung.