GIT intim - JUG Saxony Day · 2016-01-23 · GIT intim JUG SAXONY DAY 02.10.2015 Sven Oppermann...

Post on 21-Jul-2020

15 views 1 download

Transcript of GIT intim - JUG Saxony Day · 2016-01-23 · GIT intim JUG SAXONY DAY 02.10.2015 Sven Oppermann...

GIT intim

JUG SAXONY DAY 02.10.2015

Sven Oppermannsven.oppermann@gmail.com

Eigenschaften eines DVCS

Infrastruktur

Intern

In Aktion

Besonderheiten

Eigenschaften eines DVCSDVCS = Distributed Version Control System

Gerichteter Azyklischer Graph (DAG)

A B F G H I

C D E

J K

Jede Kopie eines Projektes, ist ein

vollwertiges Projekt.

Offline arbeiten möglich

Operationen sind extrem schnell

Netzwerkkommunikation nur beim Abgleich

DVCS Commit != CVCS Commit

Lokaler Commit

eindeutig identifizierbar

Snapshot Speicherung (GIT)

Branching und Merging sehr einfach

flexible Branchingmodelle

„wer wars?“ funktioniert

Lang laufende Branches sind kein Problem

Sonstiges:

Infrastruktur

$ ls -A1

.git/

pom.xml

src/

Das Repository Konfiguration

Hooks

Index

Objectstore

Referenzen

$ ls -A1

.git/

pom.xml

src/

Der Workspace Hier wird

„gearbeitet“

Workspace Index

(pre-commit)

Staging Area

Repository

Hat einen oder mehrere Eltern

eindeutig identifizierbar über

SHA1 (40 Zeichen)

Unveränderbar

Der COMMIT

A B F G H I

J

K‘

C D E

K

Der TAG

A B F G H I

J K

C D E

v1.0 v2.0

Markierung eines Standes

kann nicht verändert werden (~Commit)

Der BRANCH

A B F G H I

J K

C D E

v1.0 v2.0

master master Referenz

Veränderbar

Der REMOTE-BRANCH

A B F G H I

J K

C D E

origin/master

Eigener Namensraum

spiegelt den letzten bekannten Stand wieder

master

L

origin/master

Der HEAD

A B F G H I

J K

C D E

master

HEAD

Zeigt auf den aktuell ausgecheckten Stand

Wird vom nächsten Commit der Parent

Intern

$ ls .git

config

hooks

index

objects

HEAD

refs

Das Repository□ Konfiguration□ Hooks

□ Index

□ Objectstore

□ Referenzen

$ ls .git

config

hooks

index

objects

HEAD

refs

Das Repository□ Konfiguration

□ Hooks□ Index

□ Objectstore

□ Referenzen

$ ls .git

config

hooks

index

objects

HEAD

refs

Das Repository□ Konfiguration

□ Hooks

□ Index□ Objectstore

□ ReferenzenWorkspace

Index

Repository

$ ls .git

config

hooks

index

objects

HEAD

refs

Das Repository□ Konfiguration

□ Hooks

□ Index

□ Objectstore□ Referenzen

Key – Value Store

Hash Table

Der Objectstore

.git/objects/

89/38d6b70b1c502275d8b31bef7f7f9bf922d4ab

content

SHA18938d6b70b1c502275d8b31bef7f7f9bf922d4ab

zlib deflate compressed1001010101010111101..

type + ´ ´ + size + \0

content

.git

|- objects

| |- 89

| | |-38d6b70b1c5022...

KEY VALUE

$ git cat-file –p 8938d6

package de.geewhiz.demo;

/**

* Hello world!

*

*/

public class App

{

public static void main( String[] args )

{

System.out.println( "Hello World!" );

}

}

Der Objectstore

tree

commit tag

blob

Der Objectstore - VALUE

blobDer Objectstore –

Arbeitsverzeichnis

blob: 431a48…

blob: 8938d6…

Objectstore

demo

src

main

java

pom.xml

App.java

blobDer Objectstore –

Arbeitsverzeichnisblob 178\0

blob: 8938d6…

package de.geewhiz.demo;

/**

* Hello world!

*

*/

public class App

{

public static void main( String[] args )

{

System.out.println( "Hello World!" );

}

}

demo

src

main

java

pom.xml

App.java

Der Objectstore –

Arbeitsverzeichnis Objectstore

blob: 431a48…

tree

tree: c84e99…

tree: 1de782…

blob: 8938d6…

tree: eeef21…tree 118\0

100644 blob 431a48… pom.xml

040000 tree 1de782… src

demo

src

main

java

pom.xml

App.java

Der Objectstore –

Arbeitsverzeichnis Objectstore

commit

commit 203\0

tree c84e999ac503722dbfe4fbd3f0fe34f52d5fd972

author Sven Oppermann <sven.oppermann@gmail.com> 1442487756 +0200

committer Sven Oppermann <sven.oppermann@gmail.com> 1442487756 +0200

created demo project

commit: 6eb258…

blob: 431a48…

tree: c84e99…demo

pom.xml

Der Objectstore –

Arbeitsverzeichnis Objectstore

commit

commit 250\0

tree ...

parent ...

author Sven Oppermann <sven.oppermann@gmail.com> 1442487756 +0200

committer Sven Oppermann <sven.oppermann@gmail.com> 1442487756 +0200

second commit

commit: ……

blob: 431a48…

tree: c84e99…demo

pom.xml

Der Objectstore – tag

commit: 6eb258…

blob: 431a48…

tree: c84e99…

Arbeitsverzeichnis Objectstoretag 141\0object 6eb258a2e7effc4e60628d655489f419ab8aba31

type commit

tag v1.0

tagger Sven Oppermann <sven.oppermann@gmail.com> 1442836249 +0200

v1.0

tag: 5d9c31…

demo

pom.xml

Der Objectstore

blob tree

committag

tree

committag

blob

Der Objectstore

Unveränderbar !

Der Objectstore

blob blob

tree blob tree

blobtree tree

tree tree

commit commit

blob

Der Objectstore

blob blob

tree blob tree

tree tree blobblob

tree tree tree

commit commit commit

blob

Der Objectstore

blob blob

tree blob tree

blob treetree blob

tree tree tree

commit commit

commit

… …

$ ls .git

config

hooks

index

objects

HEAD

refs

Das Repository□ Konfiguration

□ Hooks

□ Index

□ Objectstore

□ Referenzen

.git

|- …

|- HEAD

|- refs

| |- heads

| | |- master

| |- remotes

| | |- origin

| | | |- master

| |- tags

| | |- v1.0

Die Referenzen

Die Referenzen

$ cat .git/refs/heads/master6eb258a2e7effc4e60628d655489f419ab8aba31

.git

|- …

|- HEAD

|- refs

| |- heads

| | |- master

Die Referenzen

$ cat .git/HEADref: refs/heads/master

.git

|- …

|- HEAD

|- refs

| |- heads

| | |- master

In Aktion

$ mkdir demo

$ cd demo

$ git init

$ …creating the demo project…

$ git add –all

$ git commit -m „initial setup“

commit

blob blob

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master […]

tree

df212

master

HEAD

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [df212…]

$ git branch F-189

commit

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [df212…]

df212

F-189

master

HEAD

$ git checkout F-189

commitdf212

.git

|- HEAD

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [df212…]

F-189

master

HEAD

|- HEAD [ref: refs/heads/F-189]

.git

|- HEAD [ref: refs/heads/F-189]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

$ … Implementierung …

$ git add --all

$ git commit –m „#F-189: step1“

df212

master

F-189

HEAD

e12fd

$ git checkout -b H-47 master

.git

|- HEAD [ref: refs/heads/F-189]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

| | |- H-47 [df212…]

df212

git branch H-47 master

master

e12fd

H-47F-189

HEAD

$ git checkout -b H-47 master

.git

|- HEAD [ref: refs/heads/H-47]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

| | |- H-47 [df212…]

git branch H-47 master

git checkout H-47

master

e12fd

H-47F-189

HEAD

df212

$ … Implementierung …

$ git add --all

.git

|- HEAD [ref: refs/heads/H-47]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

| | |- H-47 [df212…]

df212

master

e12fd

H-47F-189

HEAD

.git

|- HEAD [ref: refs/heads/H-47]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

| | |- H-47 [h3f12…]

$ git commit -m „#H-47: fixed“

df212

master

e12fd

h3f12

F-189

H-47

HEAD

.git

|- HEAD

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [e12fd…]

| | |- H-47 [h3f12…]

$ git checkout F-189

df212

master

e12fd

h3f12

F-189

H-47

HEAD

|- HEAD [ref: refs/heads/F-189]

.git

|- HEAD [ref: refs/heads/F-189]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [1d172…]

| | |- H-47 [h3f12…]

$ … Implementierung …

$ git commit -am „#F-189: step2“

df212

e12fd

h3f12

masterH-47

1d172

F-189

HEAD

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [df212…]

| | |- F-189 [1d172…]

| | |- H-47 [h3f12…]

$ git checkout master

df212

master

e12fd

h3f12

H-47

1d172

HEAD

F-189

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [h3f12…]

| | |- F-189 [1d172…]

| | |- H-47 [h3f12…]

$ git checkout master

$ git merge H-47

df212

fast-forward merge

h3f12

e12fd

master H-47

1d172

HEAD

F-189

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [h3f12…]

| | |- F-189 [1d172…]

| | |- H-47 [h3f12…]

$ git merge F-189

df212

3-Wege Merge

e12fd

h3f12

1d172

master H-47

F-189

HEAD

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [f1f1e…]

| | |- F-189 [1d172…]

| | |- H-47 [h3f12…]

$ git merge F-189

df212

e12fd

h3f12

1d172

H-47

F-189

f1f1e

master

HEAD

.git

|- HEAD [ref: refs/heads/master]

|- refs

| |- heads

| | |- master [f1f1e…]

$ git branch -d H-47

$ git branch -d F-189

df212

e12fd

h3f12

1d172

f1f1e

master

HEAD

Sven

Franz

Blessed Repo

b1

$

$

b2

master

Sven

Franz

Blessed Repo

$ git clone …/demo.git

$ git clone …/demo.git

b1

b1

b1

b2

b2

b2

origin/master

master

master

origin/master

master

Sven

Franz

Blessed Repo

$

$ git commit …

b1

b1

b1

b2

b2

b2

master

master

origin/master

origin/master

s1

master

Sven

Franz

Blessed Repo

$

$ git commit …

$ git commit …

b1

b1

b1

b2

b2

b2

master

master

origin/master

origin/master

s1 s2

master

Sven

Franz

Blessed Repo

$ git commit …

$ git commit …

$

b1

b1

b1

b2

b2

b2

master

origin/master

origin/master

s1

f1

s2

f2

master

master

Sven

Franz

Blessed Repo

$ git push

$

b1

b1

b1

b2

b2

b2

master

origin/master

origin/master

s1

f1

s2

f2

master

master

Sven

Franz

Blessed Repo

$ git push

$

b1

b1

b1

b2

b2

b2

master

origin/master

origin/master

s1

f1

s2

f2

master

master

Sven

Franz

Blessed Repo

$ git push

$

b1

b1

b1

b2

b2

b2

master

origin/master

origin/master

s1

f1 f2

master

s2

master

Sven

Franz

Blessed Repo

$ git push

… SUCCESS …

$

b1

b1

b1

b2

b2

b2

s1

f1

f1

s2

f2

f2

master

origin/master

master

master

origin/master

Sven

Franz

Blessed Repo

$

$ git push

… REJECTED, plz PULL …

b1

b1

b1

b2

b2

b2

origin/master

s1

f1

f1

s2

f2

f2

master

origin/master

master

master

Franz

Sven

Blessed Repo

$

$ git fetch

b1

b1

b1

b2

b2

b2

f1

s1

f1

f1

f2

s2

f2

f2

origin/master

master

origin/master master

master

Franz

Sven

Blessed Repo

$

$ git fetch

$ git merge origin/masterb1

b1

b1

b2

b2

b2

f1

s1

f1

f1

f2

s2

f2

origin/master

master

origin/master

f2

master

m1

master

Franz

origin/master

Sven

Blessed Repo

origin/master

$ git pull

$

b1

b1

b1

b2

b2

b2

f1

s1

f1

f1

f2

s2

f2

m1

f2

master

master

master

Franz

Sven

Blessed Repo

$ git push

$

b1

b1

b1

b2

b2

b2

f1

s1

f1

f1

f2

s2

f2

f2

origin/master

master

masterorigin/master

m1

master

Franz

Sven

Blessed Repo

$ git push

… SUCCESS …

$

b1

b1

b1

b2

b2

b2

f1

s1

f1

f1

s1

f2

s2

f2

f2

s2

origin/master

master

m1

master

m1

master

origin/master

Besonderheiten

CHERRY-PICK

A B E F G H

C D

master

bugfix

$

CHERRY-PICK

A B E F G H

C D

bugfix

master

$

CHERRY-PICK

A B E F G H

C D

bugfix

H‘

master

$ git checkout bugfix

$ git cherry-pick H

REBASE

$

A B C

W

origin/master

X

f-186

REBASE

$ git fetch

A B C

W

origin/master

D E

X

f-186

REBASE

$ git fetch

$ git merge origin/master

A B C

W X

f-186

D E

Y

origin/master

REBASE

$ git fetch

$ git rebase origin/master

A B C

W X

f-186

D E

origin/master

REBASE

$ git fetch

$ git rebase origin/master

A B C

W X

f-186D E

origin/master

REBASE

$ git fetch

$ git rebase origin/master

A B C

W X

f-186

D E

W‘

origin/master

REBASE

$ git fetch

$ git rebase origin/master

A B C

W X

f-186

D E

W‘ X‘

origin/master

REBASE

$

A B

S

C D

M1 M2

merge rebase

A B

S

C D

S‘ S‘‘

BISECT

$

A B F G H I

C D E

J K

master

HEAD

v1.0

BISECT

$

A B F G H I

C D E

J K

master

HEAD

v1.0

BISECT

$ git bisect start HEAD v1.0

A B F G H I

C D E

J K

master

HEAD

v1.0

BISECT

$ … TEST …

A B F G H I

C D E

J K

masterHEADv1.0

BISECT

$ … TEST …

$ git bisect good

A B F G H I

C D E

J K

masterv1.0 HEAD

BISECT

$ … TEST …

$ git bisect bad

A B F G H I

C D E

J K

masterv1.0

HEAD

BISECT

$ …

D is the first bad commit

A B F G H I

C D E

J K

masterv1.0

HEAD

BISECT

$ git bisect reset

A B F G H I

C D E

J K

masterv1.0

HEAD

BISECT

$ git bisect start HEAD v1.0

$ git bisect run ~/test.sh

A B F G H I

C D E

J K

masterv1.0

HEAD

MERGETREIBER

A B D E G

C F

master

v1.0

v2.0 v2.1

$ git merge v2.1

… SUCCESS …

https://github.com/cecom/pomutils

<version>

2.1

</version>

<version>

master

</version>

Zeig mir was drin ist…

$ git lg ^master v2.1I – (tag: v1.0) commit msg (5 minutes ago Sven)

A B D E G

C F

master

v1.0

v2.0 v2.1

H

I

J

Zeig mir was drin ist…

$ git lg v1.0..v2.0C – commit msg (17 minutes ago Sven)

F – (tag: v2.0) commit msg (14 minutes ago Sven)

A B D E G

C F

master

v1.0

v2.0 v2.1

H

I

J

Link

Zeig mir wo es drin ist…

$ git branch --contains Fmaster

A B D E G

C F

master

v1.0

v2.0 v2.1

H

I

J

Zeig mir wo es drin ist…

$ git tag --contains Fv2.0

v2.1

A B D E G

C F

master

v1.0

v2.0 v2.1

H

I

J

ENDE

My ~/.gitconfig[core]

editor = 'C:/Users/sveno/Dropbox/tools/notepad++6.8.2.bin/notepad++.exe' -multiInst -nosession -noPluginquotepath = offpreloadindex = truefscache = trueautocrlf=true

[merge]tool = merge-p4mergekeepBackup = falsekeepTemporaries = falserenormalize = truerenamelimit = 10000

[mergetool]prompt = false

[mergetool "merge-p4merge"]cmd = "C:/Users/sveno/Dropbox/tools/Perforce/p4merge.exe" -dw -tw 4 -C \"utf8\" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"keepTemporaries = falsetrustExitCode = falsekeepBackup = false

[diff]tool = diff-p4mergealgorithm = patience

[difftool "diff-p4merge"]prompt = false#if you diff a file which is new or deleted, we have to create an empty file, otherwise the tool does not startcmd = "if [ \"$LOCAL\" == \"/dev/null\" ] ; then EMPTY=\"true\"; echo. 2>$TMP/empty; LOCAL=$TMP/empty; fi; if [ \"$REMOTE\" == \"/dev/null\" ] ; then EMPTY=\"true\"; echo. 2>$TMP/empty; REMOTE=$TMP/empty; fi; \

C:/Users/sveno/Dropbox/tools/Perforce/p4merge.exe -dw -tw 4 -C \"utf8\" \"$LOCAL\" \"$REMOTE\"; if [ \"$EMPTY\" == \"true\" ] ; then rm $TMP/empty; fi;"[rerere]

enabled = true[color]

ui = auto[push]

default = simple[i18n]

commitencoding = utf-8logoutputencoding = utf-8

My ~/.gitconfig…[alias]

#show the last 10 branches, orderedb = for-each-ref --count=10 --sort=-committerdate refs/heads/ --format='%(refname:short)'

#status infos = status -sb

#log output but pretty printed on one linelg = log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr %an)%Creset' --abbrev-commit --date=relative

#dont show the commits, only show the files that i have changed on top of my remote branchdt = "!sh -c \"if [ -z \"$(git currentremote)\" ] ; then \

echo "Branch ist nicht richtig konfiguriert!" ; \else \

git diff-tree -r --name-status \$(if [ \"$(git currentremote)\" != '.' ] ; then \

echo "$(git currentremote)/" ; \fi)$(git currentmergebranch)..HEAD ; \

fi\""

#print the current remote branch, used in other commandscurrentremotebranch = "!sh -c \"git config branch.$(git currentbranch).remote\""

#print the current branch, used in other commandscurrentbranch = rev-parse --abbrev-ref HEAD

#print the current remote, used in other commandscurrentremote = "!sh -c \"if [ $# -eq 0 ] ; then \

git config branch.$(git currentbranch).remote; \else \

git config branch.$1.remote; \fi\"„

My ~/.gitconfig…

#print the current merge branch, used in other commandscurrentmergebranch = "!sh -c \"if [ $# -eq 0 ] ; then \

git config branch.$(git currentbranch).merge | sed -e 's#^refs/heads/##'; \else \

git config branch.$1.merge | sed -e 's#^refs/heads/##'; \fi\""

#show all commits and files that i changed and are on top of my remote branchlgb = "!sh -c \"if [ -z \"$(git currentremote)\" ] ; then \

echo "Branch ist nicht richtig konfiguriert!" ; \else \git log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr %an)%Creset' \

--abbrev-commit --date=relative --no-merges --name-status \$( \

if [ \"$(git currentremote)\" != '.' ] ; then \echo "$(git currentremote)/" ; \

fi\)$(git currentmergebranch)..HEAD ; \

fi\""

#push to gerritpg = "!sh -c \"if [ -z \"$(git currentremote)\" ] ; then \

echo "Branch ist nicht richtig konfiguriert!" ; \else \

git push $(git currentremote) HEAD:refs/for/$(git currentmergebranch) ; \fi; \""

A SHORT NOTE ABOUT SHA-1 (http://git-scm.com/book/ch6-1.html#A-SHORT-NOTE-ABOUT-SHA-1)

A lot of people become concerned at some point that they will, by random happenstance, have two objects

in their repository that hash to the same SHA-1 value. What then?

If you do happen to commit an object that hashes to the same SHA-1 value as a previous object in your

repository, Git will see the previous object already in your Git database and assume it was already written. If

you try to check out that object again at some point, you’ll always get the data of the first object.

However, you should be aware of how ridiculously unlikely this scenario is. The SHA-1 digest is 20 bytes or 160

bits. The number of randomly hashed objects needed to ensure a 50% probability of a single collision is about

2^80 (the formula for determining collision probability is p = (n(n-1)/2) * (1/2^160)). 2^80 is 1.2 x 10^24 or 1

million billion billion. That’s 1,200 times the number of grains of sand on the earth.

Here’s an example to give you an idea of what it would take to get a SHA-1 collision. If all 6.5 billion humans on

Earth were programming, and every second, each one was producing code that was the equivalent of the

entire Linux kernel history (1 million Git objects) and pushing it into one enormous Git repository, it would take 5

years until that repository contained enough objects to have a 50% probability of a single SHA-1 object

collision. A higher probability exists that every member of your programming team will be attacked and killed

by wolves in unrelated incidents on the same night.

Der Objectstore – SHA1