Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An introduction to git

6559581a7f64b2e0cc7f955d21b2cf6b?s=47 Olivier Berger
June 03, 2014
260

An introduction to git

Supporting material for a lecture on git

6559581a7f64b2e0cc7f955d21b2cf6b?s=128

Olivier Berger

June 03, 2014
Tweet

Transcript

  1. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen A (longer) introduction to git Olivier Berger <olivier.berger@telecom-sudparis.eu> 2014-05-03 1 / 75
  2. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen Why Git Because : 2 stage commits : cleaner commits working off-line refactoring the history of commits to make history understandable efficient allows working with other VCS on remote repositories (SVN, . . . ) Learning is hard (think of Unix shell), but practice is rewarding ;) 2 / 75
  3. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen sources Adapted from "git concepts simplified" by Sitaram Chamarty, sitaramc@gmail.com http://gitolite.com/gcs.html TBC 3 / 75
  4. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen constructing a graph of commits Git is all about constructing a nice local graph before sharing it 1 Do your mess locally 2 Commit a nice chronology 3 Rework the local graph til it’s beautiful 4 Share with others in remote repos 4 / 75
  5. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen what is a repo A repository (’repo’) is a graph of commits. In our figures, we represent SHAs with numbers for convenience. We also represent time going upward (bottom to top). 5 / 75
  6. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen working locally and committing to a repo Commiting to the repository (History) is a 2 step process : 1 staging (only what’s necessary) 2 committing (when it’s complete) 6 / 75
  7. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen basic commands First, let’s play with the command-line (CLI) Cf. basics Ipython notebook for hands on introduction 7 / 75
  8. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen graphical interfaces Now, some GUI tools 8 / 75
  9. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen atomic commits in ’git gui’ git gui allows you to stage individual lines or diff hunks, instead of all of a file’s hunks 9 / 75
  10. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen magit in Emacs TODO 10 / 75
  11. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen GUI tools : gitk 11 / 75
  12. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen GUI tools : Eclipse’s EGit 12 / 75
  13. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen Tips polishing atomic commits : check and add what needs to be committed (one bugfix or feature per commit, etc.) single line indexing in git gui undo in git gui Magit in Emacs When it’s a mess : git stash But also : single local repo + multiple working directories in parallel (locate git-new-workdir): git-new-workdir project-dir new-workdir branch . . . 13 / 75
  14. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen histories You need to understand branches You’ll want to create beautiful graphs 14 / 75
  15. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen branch Traditionally, the top of a linked list has a name. That name is a BRANCH name. 15 / 75
  16. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen more than one branch Remember we said a repo is a GRAPH? Specifically, more than one child node may be pointing at the same parent node. In this case, each ’leaf node’ is a branch, and will have a name. 16 / 75
  17. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen more than one parent commit (1/2) Well we can’t keep creating more branches without eventually merging them back. So let’s say feature X is now tested enough to be merged into the main branch, so you : git merge feature_X 17 / 75
  18. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen more than one parent commit (2/2) At this point, it’s quite common to delete the feature branch, especially if you anticipate no more "large" changes. So you can run git branch -d feature_X 18 / 75
  19. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen current branch/checked out branch There is a notion of a ’currently checked out’ branch. This is denoted by a special ref called HEAD. HEAD is a symbolic ref, which points to the ’current branch’. 19 / 75
  20. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen committing When you make a new commit, the current branch moves. Technically, whatever branch HEAD is pointing to will move. 20 / 75
  21. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen naming non-leaf nodes (1/2) It’s not just ’leaf’ nodes, but inner nodes can also have names. Recall the result of merging feature_X earlier (see the more than one parent commit section): At this point, you could leave feature_X as it is forever. Or you could delete the branch (as we showed in that section), in which case that label would simply disappear. 21 / 75
  22. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen naming non-leaf nodes (2/2) You can also continue to develop on the feature_X branch, further refining it with a view to once again merging it at some later point in time. 22 / 75
  23. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen tags More commonly, inner nodes are TAGS. 23 / 75
  24. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen the difference between branches and tags The main difference between a branch and a tag is branches move, tags don’t. When you make a commit with the "master" branch currently checked out, master will move to point to the new commit. 24 / 75
  25. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen working with others Synchronization isn’t easy Git allows you to do what you want to achieve (learning the hard way ?) 25 / 75
  26. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen cloning and sharing No more central repositories (unless by convention) 26 / 75
  27. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen what is a git URL? Git repos are accessed by providing a URL. There are typically 4 kinds of Git URLs: ssh: like ssh://[user@]host.xz[:port]/path/to/repo.git/ http: like http[s]://host.xz[:port]/path/to/repo.git/ git: like git://host.xz[:port]/path/to/repo.git/ local dir: like file:///full/path/to/reponame (see man git-clone for all the allowed syntaxes for git URLs). 27 / 75
  28. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen what is a "remote"? A remote is a short name (like an alias) used to refer to a specific git repository. Instead of always saying git fetch git://sitaramc/gitolite you can add that as a remote and use that short name instead of the long URL. For convenience, a ’remote’ called origin is automatically created when you clone a repo, pointing to the repo you cloned from. 28 / 75
  29. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen remote’s commands git remote -v git remote add gitk –all git svn (working with other projects) 29 / 75
  30. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen remote branches Git is a distributed version control system. So when you clone someone’s repo, you get all the branches in that one. 30 / 75
  31. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen multiple remotes You can have several remotes. 31 / 75
  32. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen fetching and merging from another repo (1/2) Now let’s say Sita’s repo had a couple of new commits on its master, and you run : git fetch sitas-repo 32 / 75
  33. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen fetching and merging from another repo (2/2) Now you want to merge Sita’s master branch into yours. Since your master does not have any commits that Sita’s master doesn’t have (i.e., Sita’s master is like a superset of yours), running git merge sitas-repo/master will get you this: 33 / 75
  34. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen pull is dangerous git pull instead : 1 git fetch 2 inspect in gitk [--all] 3 then : git merge, or git rebase 34 / 75
  35. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen decentralized but centralized 35 / 75
  36. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen main branches 36 / 75
  37. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen feature branches Creation: $ git checkout -b myfeature develop Switched to a new branch "myfeature" Incorporating a finished feature on develop $ git checkout develop Switched to branch ’develop’ $ git merge --no-ff myfeature Updating ea1b82a..05e9557 (Summary of changes) $ git branch -d myfeature Deleted branch myfeature (was 05e9557). $ git push origin develop 37 / 75
  38. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen merge vs merge –no-ff 38 / 75
  39. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen the 4 git object types Git keeps all its data inside a special directory called .git at the top level of your repository. Somewhere in there is what we will simply call the object store (if you’re not comfortable with that phrase, pretend it’s some sort of database). Git knows about 4 types of objects: blob – each file that you add to the repo is turned into a blob object. tree – each directory is turned into a tree object. Obviously, a tree object can contain other tree objects and blob objects, just like a directory can contain other directories and files. commit – a commit is a snapshot of your working tree at a point in time, although it contains a lot of other information also. tag – we will see this type a bit later. 39 / 75
  40. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen what is a SHA A commit is uniquely identified by a 160-bit hex value (the ’SHA’). This is computed from the tree, plus the following pieces of information: the SHA of the parent commit(s) – every commit except the very first one in the repo has at least one parent commit that the change is based upon. the commit message – what you type in the editor when you commit the author name/email/timestamp the committer name/email/timestamp (Actually, all 4 git objects types are identified by SHAs, but of course they’re computed differently for each object type. However, the SHAs of the other object types are not relevant to this discussion). In the end, as I said, it’s just a large, apparently random looking, number, which is actually a cryptographically-strong checksum. It’s usually written out as 40 hex digits. Humans are not expected to remember this number. For the purposes of this discussion, think of it as something similar to a memory address returned by malloc(). It is also GLOBALLY unique! No commit in any repo anywhere in the world will have the same SHA. (It’s not a mathematical impossibility, but just so extremely improbable that we take it as fact. If you didn’t understand that, just take it on faith). An example SHA: a30236028b7ddd65f01321af42f904479eaff549 40 / 75
  41. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen why are the arrows backward in your pictures? So why are the arrows pointing backward? Well. . . every commit knows what its parent commit is (as described in the "what is a SHA" section above). But it can’t know what its child commits are – they haven’t been made yet! Therefore a repo is like a single linked list. It cannot be a double linked list – this is because any change to the contents would change the SHA! 41 / 75
  42. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen what is a repo (again) Earlier, we saw that a repo was a graph of commits. At the file system level, however, it is basically a directory called .git which looks somewhat like this $ ls -al .git total 40 drwxrwxr-x 7 sitaram sitaram 4096 Sep 14 18:54 ./ drwx------ 3 sitaram sitaram 4096 Sep 14 18:54 ../ drwxrwxr-x 2 sitaram sitaram 4096 Sep 14 18:54 branches/ -rw-rw-r-- 1 sitaram sitaram 92 Sep 14 18:54 config -rw-rw-r-- 1 sitaram sitaram 73 Sep 14 18:54 description -rw-rw-r-- 1 sitaram sitaram 23 Sep 14 18:54 HEAD drwxrwxr-x 2 sitaram sitaram 4096 Sep 14 18:54 hooks/ drwxrwxr-x 2 sitaram sitaram 4096 Sep 14 18:54 info/ drwxrwxr-x 4 sitaram sitaram 4096 Sep 14 18:54 objects/ drwxrwxr-x 4 sitaram sitaram 4096 Sep 14 18:54 refs/ 42 / 75
  43. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen objects and branches/tags (1/4) The really, really important thing to understand is that the object store doesn’t care where the commit came from or what "branch" it was part of when it entered the object store. Once it’s there, it’s there! 43 / 75
  44. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen objects and branches/tags (2/4) - before fetch The starting point is before you did a fetch. The next two figures are after git fetch sitas-repo and git merge sitas-repo/master, respectively. 44 / 75
  45. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen objects and branches/tags (3/4) after fetch git fetch sitas-repo 45 / 75
  46. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen objects and branches/tags (4/4) after merge git merge sitas-repo/master All you did was move a pointer from one node to another. This is called a fast-forward merge 46 / 75
  47. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen advanced operations We’ll now show some advanced operations with the aid of this same tree. 47 / 75
  48. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen merging (1/4) First, let’s do merging. The merge you saw earlier was what is called a "fast-forward" merge, because your local master did not have any commits that the remote branch you were merging did not have. In practice, this is rare, especially on an active project with many developers. So let’s see what that looks like. 48 / 75
  49. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen merging (2/4) before non-ff merge The starting point is this: 49 / 75
  50. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen merging (3/4) after fetch Now, you made some changes on your local master. Meanwhile, sitas-repo has had some changes which you got by doing a fetch 50 / 75
  51. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen merging (4/4) after non-ff merge When you git merge sitas-repo/master the end result will usually look like this: This may not be what you want the graph to look like ? 51 / 75
  52. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen is the graph pretty ? Is this what you want to share with others ? Is the graph pretty think before you git push ! Remember : 1 git fetch to know what others did 2 integrate their changes and refactor at will locally 3 git push to remotes only when satisfied 52 / 75
  53. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen cherry-pick (1/3) A cherry-pick is not very commonly done – in well designed workflows it should actually be rare. However, it’s a good way to illustrate an important concept in git. We said before that a commit represents a certain set of files and directories, but since most commits have only one parent, you can think of a commit as representing a set of changes too. 53 / 75
  54. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen cherry-pick (2/3) before cherry-pick Let’s say one of your collaborators (this mythical "Sita" again!) made a whole bunch of changes to his copy of the repo. You don’t like most of these changes, except one specific change which you would like to bring in to your repo. The starting point is this: 54 / 75
  55. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen cherry picking (3/3) after cherry-pick git cherry-pick sitas-repo/master~1 This results in the following commit graph. 55 / 75
  56. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen rebasing (1/5) Instead of merging, let’s say you wanted to rebase your commits on top of Sita’s commits. First of all, what is rebasing? It’s basically transplanting a series of changes from one point in the graph to another point. So if you guessed that a rebase was (in principle) a series of cherry-picks, you’d be pretty close, at least from a concept point. 56 / 75
  57. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen rebasing (2/5) after fetch So let’s use a similar example as in the merge example before, but instead of sitas-repo, the new commits are in origin (which is the "main" server for this project). You had your own commits, and you did a git fetch origin which brought in the latest commits from "origin", so it looks like: 57 / 75
  58. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen rebasing (3/5) after rebase Now, instead of merging origin/master into your local master, you want to rebase your commits on top of origin/master. That is, you want to pretend your local changes were made after commit 13 on the origin. So you run git rebase origin/master and this is the result: 58 / 75
  59. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen rebasing (4/5) Unlike cherry-pick, a rebase is quite often done in real life. Rebase also has some other forms. This form is one, but the most common is when a developer wants to re-arrange his own local commits in a more logical sequence before publishing/pushing them. 59 / 75
  60. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen rebasing (5/5) I often do the eqvt of changing this: where "22delta" is a minor fixup to "22", into: using: git rebase -i Try this with Magit ! 60 / 75
  61. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen non fast-forward merge (1/2) Here’s the starting point : 61 / 75
  62. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen non fast-forward merge (2/2) git merge --no-ff feature_X 62 / 75
  63. you’re ready for : "A successful Git branching model" cf.

    : A successful Git branching model
  64. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen resolving conflicts git mergetool Emacs + M-x vc-resolve-conflicts 64 / 75
  65. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen brutally or you can : git merge --squash --no-commit 65 / 75
  66. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen Resources git concepts simplified A Visual Git Reference git cheat sheet An introduction to git-svn for Subversion/SVK users and deserters pro git mémento git à 100% A successful Git branching model 66 / 75
  67. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen copyrights + license ©Copyright Sitaram Chamarty, sitaramc@gmail.com (for parts originally in git concepts simplified) ©Copyright Mark Lodato, lodatom@gmail.com (for parts from A Visual Git Reference) ©Copyright Vincent Driessen (for parts from A successful Git branching model) ©Copyright 2012-2014 Olivier Berger + Institut Mines Télécom (the sources are available in https://gitorious.org/olberger/ presentations/trees/master/30mins-intro-git on the ’longer’ branch) This documentation is provided under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0. Made with org-mode (under emacs, to generate beamer slides with inline dot graphs) 67 / 75
  68. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen the confusion about checkout versus reset The basic difference is very simple: checkout changes what your current branch is (i.e., it changes where HEAD is pointing to) reset changes which commit the current branch is pointing to 68 / 75
  69. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen checkout or reset As you can see, your current branch, when you start, is "master" (indicated by where HEAD is pointing). A "checkout" changes what is your current branch – it is now "devel", and so any new commits you make now will go on devel, not master. On the other hand, a reset changes what commit your current branch points to. Your branch is still master, but now it is pointing to what could potentially be a completely different history. 69 / 75
  70. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen detached HEAD (1/2) All this time you have seen HEAD pointing to a branch name, and the branch itself pointing to a commit. Then, when you make a commit, the branch moves to the new commit (although HEAD still continue to point to the branch name). 70 / 75
  71. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen detached HEAD (2/2) Now see what happens when you git checkout v1.0: Notice the subtle difference? 71 / 75
  72. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen commit on detached HEAD So from this point on, if you make a commit, only HEAD changes, nothing else, since it is no longer "attached" to any local branch name The reason this is considered dangerous is that, if you now do git checkout master, you get this: 72 / 75
  73. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen re-attaching the HEAD Modern git will warn you about losing commits on a detached HEAD if you’re at the command line, and tell you how to recover (immediately). Recovery is quite easy. If you realised you’re on a detached HEAD before you switched to some other branch: git checkout -b newbranch 73 / 75
  74. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen creating remote repos bare repos fusionforge 74 / 75
  75. introduction basics branches & tags local & remote repos workflow

    .git object store advanced operations end appen moare guis msysgit (http://msysgit.github.io/) (CLI + git distrib ala Linux) tortoiseGIT (https://code.google.com/p/tortoisegit/) . . . http://git-scm.com/downloads/guis 75 / 75