PROGRAMMIERPRAKTIKUM 2015 VERSIONSKONTROLLE MIT GIT Tobias Witt EINFÜHRUNG WELCHE PROBLEME KÖNNEN BEI DER ARBEIT IM TEAM AUFTRETEN? ZIELE • Protokollierung von Veränderungen • Wiederherstellung alter Zustände • Koordination gemeinsamer Arbeit • Parallele Entwicklungszweige AUSKOMMENTIEREN public class MyClass { private int myInt = 0; } public class MyClass { //private int myInt = 0; public int myInt = 0; } DATEIEN KOPIEREN MyClass.1.java MyClass.java public class MyClass { private int myInt = 0; } public class MyClass { public int myInt = 0; } VERSIONSKONTROLLE • Systeme: CVS, SVN, Mercurial, Bazaar • Für diese Vorlesung: GIT $ # # # # $ git status On branch master Changes not staged for commit: modified: MyClass.java git diff public class MyClass { - private int myInt = 0; + public int myInt = 0; } $ git commit -m "Make myInt public" MyClass.java [master a5d0adf] Make myInt public 1 file changed, 1 insertion(+), 1 deletion(-) BEGRIFFE Working Copy Alle Dateien des Projekts in der aktuell gewählten Version Staging Area Änderungen für die nächste Version Repository Speicherort für Versionen, Zweige und Markierungen Remote Entferntes Repository Commit Eine Version. Committen = einen Commit machen Branch Entwicklungszweig Tag Alias einer Version ARBEITSABLAUF 1. Synchronisation 2. Arbeit an den Dateien Lokales Repository MyClass.java MyClass.java @3cabd97 @3cabd97 3. Commit MyClass.java 4. Synchronisation 5. Lösen von Kon!ikten 6. Upload der Commits 1 Remote Repository 4 MyClass.java @deadbee @deadbee MyClass.java MyClass.java @acab666 6 @acab666 BEST PRACTICES • Commit kein Ersatz für Undo • Gemeinsamer Commit zusammengehöriger Änderungen • Getrennter Commit verschiedener Änderungen • Kein Commit von unsauberem Code ‣ In den Master-Branch GESCHICHTE • 2005, Linus Torvalds • Linux Kernel • Anforderungen: • ‣ Verteilte Arbeitsabläufe ‣ Sehr hohe Sicherheit gegen Verfälschungen Heutiger Maintainer: Junio Hamano ARBEIT MIT GIT $ git init Initialized empty Git repository in /MyProject/.git/ Arbeitskopie Repository Erstelle .gitignore Datei $ git status # On branch master # # Initial commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # .gitignore nothing added to commit but untracked files present (use "git add" to track) Füge .gitignore Datei zur Staging Area hinzu und committe $ git add .gitignore $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: .gitignore # $ git commit -m "Initial Commit" [master (root-commit) 4e3fa80] Initial commit 1 file changed, 1 insertion(+) create mode 100644 .gitignore OBJEKTE Initial Commit 5eaaede Tree 82e3a75 Commit Tree (Wurzelbaum) Blob .gitignore 9de29bb BLOBS • Referenzieren Dateiinhalte • SHA1-Hash aus Dateiinhalt • Wiederverwendung • Mindestens ein Blob pro Commit ‣ keine leeren Verzeichnisse $ git show 9de29bb *.swp TREES • • • Referenzieren Verzeichnisse SHA1-Hash aus enthaltenen Blobs und Trees Tree + Blob = Dateireferenz $ git show 82e3a75 tree 82e3a75 .gitignore COMMITS • Referenzieren Versionen • SHA1-Hash aus Autor, Zeitpunkt, Trees, Blobs und Elterncommit • Commit-Bezeichner grundsätzlich eindeutig COMMITS $ git show 5eaaede commit 5eaaede... Author: Tobias Witt <[email protected]> Date: Sun Mar 30 22:48:01 2014 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp src Tree cccb338 Add src dir Tree 8badf00d fdacab6 .gitignore "bin/" b00b1e5 Add MyClass Tree b16b00b fadbeef MyClass.java "public cl..." 80ff1ce Initial Commit Tree 4e3fa80 9b27344 .gitignore "*.swp" 1377554 MyClass.java .gitignore ZUSTÄNDE VON DATEIEN Untracked Unmodified Modified Staged Datei hinzufügen (git add) Datei committen (git commit) Datei bearbeiten Datei hinzufügen (git add) Datei entfernen (git rm) DER GRAPH public class MyClass { MyClass.java@a5d0adf public int myInt = 0; } Make myInt public a5d0adf $ git checkout 874d218 HEAD is now at 874d218… Add file Detached Head public class MyClass { MyClass.java@874d218 private int myInt = 0; } Add MyClass 874d218 HEAD public class MyClass { public int myInt = 0; } Make myInt public a5d0adf $ git reset --hard 874d218 HEAD is now at 874d218... Add file public class MyClass { private int myInt = 0; } Add MyClass 874d218 Master HEAD BRANCHES • Referenz auf Commits ‣ • Alle Vorgänger Teil vom Branch Hierarchie: Repository/Branch-Name ‣ remote/master und master verschiedene Branches public class MyClass { public int myInt = 0; } Make myInt public a5d0adf $ git branch Menu $ git checkout Menu Switched to branch 'Menu' $ git reset --hard HEAD~1 HEAD is now at 874d218 Add MyClass public class MyClass { private int myInt = 0; } Add MyClass 874d218 Master Menu HEAD DumbIdea Bug#91v2 D3 C3 HEAD D2 Bug#91 B3 C2 C1 Master D1 M3 B2 $ git merge DumbIdea M2 B1 M1 Master DumbIdea D3 Bug#91v2 D2 C3 Bug#91 $ git merge DumbIdea $ git branch -D Bug#91 D1 B3 C2 M3 B2 C1 M2 B1 M1 HEAD DumbIdea $ git merge DumbIdea $ git branch -D Bug#91 $ git merge Bug#91v2 Master Bug#91v2 D3 C3 D2 C2 D1 C1 M3 B2 M2 B1 M1 Master M4 Merge-Commit DumbIdea $ $ $ $ git git git git merge DumbIdea branch -D Bug#91 merge Bug#91v2 tag v1.2 v1.2 D3 C3 D2 C2 D1 C1 M3 B2 M2 B1 M1 Bug#91v2 Gian Tobi D D D M M M M Max C C C B B Origin Pakan PUSH • Upload der Commits • Kein Zusammenführen von master und origin/master $ git push origin master Remotename Branchname FETCH, MERGE & PULL • Fetch Synchronisation mit Remote Repository $ git fetch origin master Remotename Branchname • Merge Zusammenführen von Remote Branches $ git merge origin/master • Konfliktpotential Pull Fetch gefolgt von Merge $ git pull origin master Rücksichtsloser Merge PLÄTZE FÜR DATEIEN Working Copy Staging Area Local Repository Remote Repository Datei hinzufügen (git add) Datei committen (git commit) Commits pushen (git push) Commits fetchen (git fetch) Commits zusammenführen (git merge) Commits pullen (git pull) MERGE VS. REBASE Eventuell unerwünscht HEAD HEAD Bug Master Bug Master Master Bug Master Bug $ git merge Bug $ git rebase master BEISPIEL PROJEKT .gitignore # IntelliJ .idea/ *.iml *.iws out/ doc/ # Java *.class hs_err_pid* Main.java package de.hhu.propra14.team66; public class Main { public static void main(String[] args) { } } $ git config --global user.name "Tobias Witt" Tobi $ git config --global user.email [email protected] IntelliJ-Projekt $ git init Initialized empty Git repository in /Users/tobi/Team66/.git/ $ git status # On branch master # # Initial commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # .gitignore # src/ nothing added to commit but untracked files present (use "git add" to track) Tobi $ git add . Tobi $ git commit -m "Initial Commit" [master (root-commit) b966b35] Initial Commit 2 file changed, 15 insertions(+) create mode 100644 .gitignore $ git remote add origin [email protected]:ProPra14/team66.git $ git push -u origin master Counting objects: 4, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 558 bytes, done. Total 4 (delta 0), reused 0 (delta 0) Neuer Remote Branch To [email protected]:ProPra14/team66.git * [new branch] master -> master Branch master set up to track remote branch master from origin. Tobi Origin master origin/master 1 1 $ git config --global user.name "Arsham Sabbaghi Asl" Pakan $ git config --global user.email [email protected] $ git clone [email protected]:ProPra14/team66.git Cloning into 'team66'... remote: Counting objects: 4, done. remote: Compressing objects: 100% (4/4), done. remote: Total 5 (delta 0), reused 0 (delta 0) Receiving objects: 100% (4/4), done. $ git add src/de/hhu/propra14/team66/Game.java $ git commit -m "Add Game class" [master b9ec7c1] Add Game class 1 file changed, 15 insertions(+) create mode 100644 src/de/hhu/propra14/team66/Game.java $ git push ... To [email protected]:ProPra14/team66.git b966b35..b9ec7c1 master -> master Tobi master 1 Origin Pakan origin/master master 2 2 1 1 Nicht im Klon klonen ! $ git pull Updating b966b35..b9ec7c1 Fast-forward src/Game.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/Game.java Tobi Tobi Origin Pakan master origin/master master 2 2 2 1 1 1 $ git diff ... for + int + for + + + } ... Tobi (int i = 0; i < rolls.length; i++) score += rolls[i]; score = 0, roll = 0; (int frame = 0; frame < rolls.length/2; frame++) { score += rolls[roll] + rolls[roll+1]; roll += 2; Konflikt Pakan $ git diff ... for (int i = 0; i < rolls.length; i++) score += rolls[i]; + int score = 0, roll = 0; + for (int frame = 0; frame < rolls.length/2; frame++) { + score += scoreIn(roll); + roll += 2; ... + + private int scoreIn(int roll) { + return rolls[roll] + rolls[roll+1]; + } } Pakan $ git commit -am "Make Game spare ready" [master 47294f3] Make Game spare ready 1 file changed, 9 insertions(+), 3 deletions(-) $ git push Counting objects: 7, done. Delta compression using up to 2 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (4/4), 512 bytes, done. Total 4 (delta 1), reused 0 (delta 0) To [email protected]:ProPra14/team66.git b9ec7c1..47294f3 master -> master Impliziert git add . Tobi Origin Pakan Sicher (relativ) origin/master master 3 3 2 2 2 1 1 1 master Tobi $ git commit -am "Game is now spare ready" [master 4abd3b5] Game is now spare ready 1 file changed, 5 insertions(+), 3 deletions(-) $ git push To [email protected]:ProPra14/team66.git ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '[email protected]:ProPra14/team66.git' hint: Updates were rejected because the tip of your current branch hint: is behind its remote counterpart. Merge the remote changes hint: (e.g. 'git pull') before pushing again. See the 'Note about hint: fast-forwards' in 'git push --help' for details. Tobi $ git commit -am "Game is now spare ready" [master 4abd3b5] Game is now spare ready 1 file changed, 5 insertions(+), 3 deletions(-) $ git push To [email protected]:ProPra14/team66.git ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to '[email protected]:ProPra14/team66.git' Schlechter hint: Updates were rejected because the tip of your current branch Vorschlag hint: is behind its remote counterpart. Merge the remote changes hint: (e.g. 'git pull') before pushing again. See the 'Note about hint: fast-forwards' in 'git push --help' for details. $ git pull ... From github.com:ProPra14/team66 b9ec7c1..47294f3 master -> origin/master Auto-merging src/Game.java CONFLICT (content): Merge conflict in src/Game.java Automatic merge failed; fix conflicts and then commit the result. $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 1 and 1 different commit each, respectively. # # Unmerged paths: # (use "git add/rm <file>..." as appropriate to mark resolution) # # both modified: src/Game.java # no changes added to commit (use "git add" and/or "git commit -a") src/Game.java public class Game { //... public int score() { int score = 0, i = 0; Lokal for (int frame = 0; frame < rolls.length/2; frame++) { <<<<<<< HEAD score += rolls[i] + rolls[i+1]; ======= score += scoreIn(i); >>>>>>> 5b3dd08272b5db72db9c850035a589cf61de170e i += 2; Remote } return score; } //... } //... int score = 0, i = 0; for (int frame = 0; frame < rolls.length/2; frame++) { score += scoreIn(i); i += 2; } //... $ git commit -am "Merge origin/master" Tobi [master 4f25a92] Merge origin/master $ git push Counting objects: 11, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (5/5), 534 bytes, done. Total 5 (delta 2), reused 0 (delta 0) To [email protected]:ProPra14/team66.git 5b3dd08..4f25a92 master -> master Pakan $ git pull Tobi master Origin Pakan origin/master master 4 4 4 3' 2 3 3 3' 2 3 3' 2 origin/master 1 1 1 PROJEKT https://git.hhu.de/programmierpraktikum-2015/team<nr> [email protected]:programmierpraktikum-2015/team<nr>.git $ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/tobi/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Private Key Enter same passphrase again: Your identification has been saved in /Users/tobi/.ssh/id_rsa. Your public key has been saved in /Users/tobi/.ssh/id_rsa.pub. The key fingerprint is: Public Key ce:57:85:83:13:a8:d4:0c:44:a1:e6:ca:e3:41:be:5c [email protected] The key's randomart image is: +--[ RSA 2048]----+ | o== .. | | .. + o . | | o. . o o . | | o . . o | | . . S . | | + . o . | | * E o . | | o = . | | + | +-----------------+ Public(!) Key • Git-Commits = Leistungsnachweis • Regelmäßig Committen • Sinnvolle Commit-Kommentare • Weitere Informationen in den Übungen HILFSQUELLEN • • • GIT-Homepage ‣ http://git-scm.com ‣ http://git-scm.com/book GIT-Cheat-Sheets ‣ https://raw.github.com/AlexZeitler/gitcheatsheet/master/gitcheatsheet.pdf ‣ http://www.ndpsoftware.com/git-cheatsheet.html ‣ http://byte.kde.org/~zrusin/git/git-cheat-sheet-medium.png Git for ages 4 and up ‣ https://www.youtube.com/watch?v=1#BJ4sVUb4 BILDQUELLEN Bild Quelle Memes http://quickmeme.com, http://imgflip.com/memegenerator, http://alltheragefaces.com Github-Comic http://www.flickr.com/photos/dullhunk/6251011880 Robot that Screams http://www.hornoxe.com/wp-content/picdumps/ picdump305/hornoxe.com_picdump305_016.jpg