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

Being an Effective Git (User)

Being an Effective Git (User)

Making the Jump From Subversion.

Talk given at GroupSpaces HQ on 9th December 2010

Dave Ingram

March 23, 2012
Tweet

More Decks by Dave Ingram

Other Decks in Programming

Transcript

  1. Being an Effective Git (User)
    Making the jump from Subversion
    Dave Ingram
    @dmi
    March 23, 2012

    View Slide

  2. Git is not Subversion
    • The two are very different
    • Not just in operation, but in the way you must think

    View Slide

  3. Git is not Subversion
    • The two are very different
    • Not just in operation, but in the way you must think
    • Subversion commit: A snapshot in time
    • Git commit: A set of changes; a diff

    View Slide

  4. Git is not Subversion
    • The two are very different
    • Not just in operation, but in the way you must think
    • Subversion commit: A snapshot in time
    • Git commit: A set of changes; a diff
    • Subversion branch: A cheap copy of the tree
    • Git branch: A convenient, changable identifier for a commit and its
    ancestors

    View Slide

  5. How do I use it?

    View Slide

  6. Basic commands
    • Basic git commands are quite similar to subversion
    • Both use subcommands of a master program, e.g. git status and
    svn status
    • Git has man pages for each command: git command --help
    • Most commands are (more or less) identical
    • Be warned: there are some differences

    View Slide

  7. Basic commands
    Subversion Git
    svn checkout git clone
    svn status git status
    svn diff git diff
    svn update git pull∗
    svn commit git commit -a && git push
    svn switch branch URL git checkout branch name
    svn revert path git checkout -- path
    svn log git log
    svn merge git merge or
    git cherry-pick
    ∗Not really identical

    View Slide

  8. Setting user info
    • Git needs to know who you are!
    • The very first git commands you should run:
    • git config --global user.name ' your name '
    • git config --global user.email email
    • This information will identify your commits

    View Slide

  9. Workflow Walkthrough

    View Slide

  10. Overview
    clone branch edit status diff stage check commit merge/
    push

    View Slide

  11. Setting up your working copy
    Start off by getting a copy of the repository:
    $ git clone url dir
    Initialized empty Git repository in dir /.git/
    remote: Counting objects: 77, done.
    remote: Compressing objects: 100% (76/76), done.
    remote: Total 77 (delta 49), reused 0 (delta 0)
    Receiving objects: 100% (77/77), 1.97 MiB | 1.26 MiB/s, done.
    Resolving deltas: 100% (49/49), done.
    $ cd dir
    clone branch edit status diff stage check commit merge/push

    View Slide

  12. Starting work on a feature
    A newly-cloned repository will start with the master branch
    checked out. It’s a good idea to put every feature in its own branch,
    unless it’s a trivial bugfix:
    $ git co -b branch
    This will create the branch branch, and switch to it. Now you can
    actually start to edit files.
    clone branch edit status diff stage check commit merge/push

    View Slide

  13. Checking status
    $ git status
    # On branch branch
    # Changed but not updated:
    # (use "git add ..." to update what will be committed)
    # (use "git checkout -- ..." to discard changes in working
    directory)
    #
    # modified: app/models/Comment.php
    # modified: app/views/CommentView.php
    #
    # Untracked files:
    # (use "git add ..." to include in what will be committed)
    #
    # app/models/CommentThread.php
    # www/comments/threads/
    no changes added to commit (use "git add" and/or "git commit -a")
    clone branch edit status diff stage check commit merge/push

    View Slide

  14. Seeing what has changed
    To see details of what has changed, use:
    $ git diff
    diff --git a/app/models/Comment.php b/app/models/Comment.php
    index 07ac8b3..627b51b 100644
    --- a/app/models/Comment.php
    +++ b/app/models/Comment.php
    @@ -1,4 +1,5 @@
    require once('app/models/Article.php');
    +require once('app/models/CommentThread.php');
    class Comment extends Model {
    @@ -16,5 +17,75 @@
    clone branch edit status diff stage check commit merge/push

    View Slide

  15. Preparing a commit
    With git, you must “stage” changes to be committed. This gives you full
    control and helps ensure that you don’t commit anything you don’t intend.
    $ git add app/models/Comment*.php
    $ git add app/views/CommentView.php
    $ git add www/comments/threads
    If you want to stage everything, you could also do:
    $ git add .
    clone branch edit status diff stage check commit merge/push

    View Slide

  16. Seeing what will be committed
    To see details of what will be committed, like git diff, use:
    $ git status -v
    This will show you every change waiting to be committed, in the same
    style as git diff.
    clone branch edit status diff stage check commit merge/push

    View Slide

  17. Making a commit
    Actually making a commit is very simple:
    $ git commit -m message
    If you want to provide a longer commit message, you can use your editor
    by running:
    $ git commit
    Note that the first line of a commit message should be a short summary,
    and the second line must be blank. Any further lines can contain more
    details about the commit.
    clone branch edit status diff stage check commit merge/push

    View Slide

  18. Merging your branch back
    After the feature is finished, the branch needs to be merged back. First,
    change to master:
    $ git checkout master
    Next, pull any recent changes from the central repository:
    $ git pull
    Then merge in the branch and push it back to the main repository:
    $ git merge branch
    $ git push
    clone branch edit status diff stage check commit merge/push

    View Slide

  19. Basic workflow summary
    $ git clone url dir
    $ cd dir
    $ git co -b branch
    edit files...
    $ git status
    $ git diff
    $ git add .
    $ git status -v
    $ git commit -m message
    $ git checkout master
    $ git pull
    $ git merge branch
    $ git push
    Feature loop
    Commit loop

    View Slide

  20. Remember!
    • Git is not Subversion
    • All commits are local until you push them!
    • Make sure you push branches regularly (e.g. daily)
    • If your machine dies, unpushed commits will be lost
    • Git commands work on the whole repository, not just the current
    directory and those below
    • Git works best when you frequently make many small commits

    View Slide

  21. Other useful commands
    There are two other commands that are useful to know, although you may
    not use them every day:
    • git stash — “stash” and restore your changes to the working copy,
    if you need it to be clean
    • git bisect — quickly narrow down the commit which introduced a
    bug (to be covered later)

    View Slide

  22. git stash
    • You may find you need to interrupt what you’re doing in order to fix a
    bug, without wanting to commit
    • Although it’s possible to go back and edit commits that haven’t been
    pushed, it can be troublesome
    • git stash will save the current state of your working copy to a stack,
    then reset it to being clean
    • You can switch branches or do whatever is necessary to fix the
    immediate issue
    • When you’re done, switch back to the branch you were on and run git
    stash pop to return to where you last were

    View Slide

  23. git stash
    ...work work work
    need to fix an urgent bug!
    $ git stash
    your working copy is now clean, with no uncommitted changes
    $ git checkout master
    $ git pull
    do emergency fix
    $ git add .
    $ git commit -m 'Emergency fix for bug'
    $ git push
    $ git stash list
    stash@{0}: On mybranch: Added threading
    stash@{1}: On other-branch: Fixed widget
    $ git checkout mybranch
    $ git stash pop
    work work work ...

    View Slide

  24. Branching and Merging

    View Slide

  25. History Styles
    • History in Subversion is mostly linear:
    • Monotonically increasing global revision IDs
    • Branching can be expensive, slow, and inconvenient
    • Branches are often only made for large features

    View Slide

  26. History Styles
    • History in Subversion is mostly linear:
    • Monotonically increasing global revision IDs
    • Branching can be expensive, slow, and inconvenient
    • Branches are often only made for large features
    • In git, history tends to be very branchy:
    • No sequential revision IDs
    • Branching is easy, fast, and convenient
    • Tend to create tiny branches for each individual feature

    View Slide

  27. Subversion branching
    • In Subversion, a branch is a cheap copy of trunk (or another branch)
    • Once you commit to a branch, that commit always belongs to that
    branch

    View Slide

  28. Subversion branching
    • In Subversion, a branch is a cheap copy of trunk (or another branch)
    • Once you commit to a branch, that commit always belongs to that
    branch
    • Branches can be deleted without being merged, but are still
    recoverable by traversing history

    View Slide

  29. Subversion branching
    • In Subversion, a branch is a cheap copy of trunk (or another branch)
    • Once you commit to a branch, that commit always belongs to that
    branch
    • Branches can be deleted without being merged, but are still
    recoverable by traversing history
    • Merging or cherry-picking loses information about where the changes
    came from (unless mentioned in the commit message)

    View Slide

  30. Subversion branching
    • In Subversion, a branch is a cheap copy of trunk (or another branch)
    • Once you commit to a branch, that commit always belongs to that
    branch
    • Branches can be deleted without being merged, but are still
    recoverable by traversing history
    • Merging or cherry-picking loses information about where the changes
    came from (unless mentioned in the commit message)
    • Merging also squashes an entire branch worth of changes into a
    single commit

    View Slide

  31. Subversion branching
    • In Subversion, a branch is a cheap copy of trunk (or another branch)
    • Once you commit to a branch, that commit always belongs to that
    branch
    • Branches can be deleted without being merged, but are still
    recoverable by traversing history
    • Merging or cherry-picking loses information about where the changes
    came from (unless mentioned in the commit message)
    • Merging also squashes an entire branch worth of changes into a
    single commit
    • A bit like copying an entire directory with cp -r

    View Slide

  32. Subversion branching
    You start out with commits on trunk
    trunk

    View Slide

  33. Subversion branching
    You then create mybranch via svn cp
    trunk
    mybranch

    View Slide

  34. Subversion branching
    One commit later on trunk. . .
    trunk
    mybranch

    View Slide

  35. Subversion branching
    You create yourbranch via svn cp
    trunk
    mybranch
    yourbranch

    View Slide

  36. Subversion branching
    A few commits later on all branches, you decide to merge mybranch back
    into trunk
    trunk
    mybranch
    yourbranch

    View Slide

  37. Subversion branching
    You change to trunk and run svn merge .../mybranch with the right
    revision range to import the changes, and commit
    trunk
    mybranch
    yourbranch

    View Slide

  38. Subversion branching
    At any given time, these commits are on their branch and only ever on
    that branch
    trunk
    mybranch
    yourbranch

    View Slide

  39. Subversion branching
    Notice that this commit is on trunk and embodies all the changes from
    mybranch, but Subversion does not remember where it came from – it
    looks like a normal commit

    View Slide

  40. Git branching
    • In Git, a branch is a convenient non-permanent name for a commit
    • The branch a commit belongs to is any branch it is reachable from
    • This means that if you trace a path back from a branch to the root, all
    of the commits you pass through are reachable from that branch

    View Slide

  41. Git branching
    • In Git, a branch is a convenient non-permanent name for a commit
    • The branch a commit belongs to is any branch it is reachable from
    • This means that if you trace a path back from a branch to the root, all
    of the commits you pass through are reachable from that branch
    • If an unmerged, unpushed branch is deleted, it is gone*

    View Slide

  42. Git branching
    • In Git, a branch is a convenient non-permanent name for a commit
    • The branch a commit belongs to is any branch it is reachable from
    • This means that if you trace a path back from a branch to the root, all
    of the commits you pass through are reachable from that branch
    • If an unmerged, unpushed branch is deleted, it is gone*
    • Cherry-picking loses ancestry by default, but can be easily changed

    View Slide

  43. Git branching
    • In Git, a branch is a convenient non-permanent name for a commit
    • The branch a commit belongs to is any branch it is reachable from
    • This means that if you trace a path back from a branch to the root, all
    of the commits you pass through are reachable from that branch
    • If an unmerged, unpushed branch is deleted, it is gone*
    • Cherry-picking loses ancestry by default, but can be easily changed
    • Merging keeps the branch, but loses the name attached to it

    View Slide

  44. Git branching
    • In Git, a branch is a convenient non-permanent name for a commit
    • The branch a commit belongs to is any branch it is reachable from
    • This means that if you trace a path back from a branch to the root, all
    of the commits you pass through are reachable from that branch
    • If an unmerged, unpushed branch is deleted, it is gone*
    • Cherry-picking loses ancestry by default, but can be easily changed
    • Merging keeps the branch, but loses the name attached to it
    • A bit like creating a symlink with ln -s

    View Slide

  45. Git branching
    You start out with commits on trunk
    trunk

    View Slide

  46. Git branching
    You then create mybranch via git br, which is not a commit
    trunk
    mybranch

    View Slide

  47. Git branching
    One commit later on trunk. . .
    trunk
    mybranch

    View Slide

  48. Git branching
    You create yourbranch via git br
    trunk
    mybranch
    yourbranch

    View Slide

  49. Git branching
    As you commit to each branch, their pointers move
    trunk
    mybranch
    yourbranch

    View Slide

  50. Git branching
    A few commits later, you’re ready to merge mybranch back into trunk
    trunk
    mybranch
    yourbranch

    View Slide

  51. Git branching
    To merge, change to trunk (git checkout trunk) and import the
    changes by running git merge mybranch
    trunk
    mybranch
    yourbranch

    View Slide

  52. Git branching
    Notice that this commit is on trunk, and all of mybranch is reachable from
    it. If you delete mybranch, then its history remains.
    trunk
    mybranch
    yourbranch

    View Slide

  53. That’s great and all, but. . .
    • . . . what are the advantages?
    • Git’s branch tracking lets you do complicated merges really easily
    • Long-lived feature branches are trivial
    • Branching and merging is no longer something to fear!
    • Let’s see an example

    View Slide

  54. Long-lived feature branch
    After your big-feature branch has been running for a while, you need
    something from trunk
    trunk
    big-feature

    View Slide

  55. Long-lived feature branch
    Simply merge the commits from trunk and carry on
    trunk
    big-feature

    View Slide

  56. Long-lived feature branch
    A few commits later, there is a fix on trunk that you also need. . .
    trunk
    big-feature

    View Slide

  57. Long-lived feature branch
    Just merge again from trunk to big-feature, and git will work out what to
    do
    trunk
    big-feature

    View Slide

  58. Long-lived feature branch
    Eventually you’re at the stage where you’re ready to merge big-feature
    back into trunk
    trunk
    big-feature

    View Slide

  59. Long-lived feature branch
    Change to trunk, run git merge big-feature and git will merge back
    with few or no problems
    trunk
    big-feature

    View Slide

  60. Release management
    qa
    live
    master
    20101204-163152 20101211-145819

    View Slide

  61. Release management
    qa
    live
    master
    20101204-163152 20101211-145819
    All development happens around the master branch

    View Slide

  62. Release management
    qa
    live
    master
    20101204-163152 20101211-145819
    Prepare to deploy by merging from master to qa

    View Slide

  63. Release management
    qa
    live
    master
    20101204-163152 20101211-145819
    All fixes happen on master so qa is kept merge-only

    View Slide

  64. Release management
    qa
    live
    master
    20101204-163152 20101211-145819
    A deploy is simply a merge from qa to live plus a tag

    View Slide

  65. Release management
    qa
    live
    master
    20101204-163152 20101211-145819
    Hotfixes happen on live and get merged back to master

    View Slide

  66. Things to remember
    • Git has very powerful merge tracking

    View Slide

  67. Things to remember
    • Git has very powerful merge tracking
    • Because it tracks content, it can even handle changes to a file that has
    been renamed in another branch

    View Slide

  68. Things to remember
    • Git has very powerful merge tracking
    • Because it tracks content, it can even handle changes to a file that has
    been renamed in another branch
    • Problems are only likely to come up if:
    • the same part of a file is edited in both branches and git can’t work
    out a resolution

    View Slide

  69. Things to remember
    • Git has very powerful merge tracking
    • Because it tracks content, it can even handle changes to a file that has
    been renamed in another branch
    • Problems are only likely to come up if:
    • the same part of a file is edited in both branches and git can’t work
    out a resolution
    • a file is deleted (not moved) in one branch and edited in another

    View Slide

  70. Things to remember
    • Git has very powerful merge tracking
    • Because it tracks content, it can even handle changes to a file that has
    been renamed in another branch
    • Problems are only likely to come up if:
    • the same part of a file is edited in both branches and git can’t work
    out a resolution
    • a file is deleted (not moved) in one branch and edited in another
    • two files are created with the same path in each branch

    View Slide

  71. Tracking down bugs

    View Slide

  72. Final bit of git magic (for now)
    • Sometimes a bug is found that has probably existed for a long time, as
    an unexpected side-effect of an earlier change
    • If you know that it used to work, then tracking down the commit which
    actually caused the bug can be a big task
    • This is where git bisect comes in useful

    View Slide

  73. git bisect
    • git bisect allows you to do a binary search on commits to find the
    one that caused the bug
    • You could manually jump between revisions, but that’s very
    time-consuming
    • With git bisect you must still find a good commit, but you can just
    keep jumping back in history to find it
    • Just tell git whether a commit is good or bad, and it does the rest
    • Note: needs a clean working copy when you begin

    View Slide

  74. git bisect
    We know that the current commit is bad and contains a bug that
    wasn’t there before, but we don’t know when it was introduced. We
    start git bisect, (using git stash to save changes from our
    working copy if necessary):
    $ git bisect start

    View Slide

  75. git bisect
    We know that the current commit is bad and contains a bug that
    wasn’t there before, but we don’t know when it was introduced. We
    start git bisect, (using git stash to save changes from our
    working copy if necessary):
    $ git bisect start
    We now mark the current commit as being “bad” (i.e. it has the
    bug)
    $ git bisect bad

    View Slide

  76. git bisect
    We then jump back in history (say fifteen commits at a time) until
    we find a commit without the bug.
    $ git checkout HEAD~15
    Note: To better illustrate what git checkout is doing, the animation goes back
    5 commits at a time.

    View Slide

  77. git bisect
    We then jump back in history (say fifteen commits at a time) until
    we find a commit without the bug.
    $ git checkout HEAD~15
    Note: To better illustrate what git checkout is doing, the animation goes back
    5 commits at a time.

    View Slide

  78. git bisect
    We then jump back in history (say fifteen commits at a time) until
    we find a commit without the bug.
    $ git checkout HEAD~15
    Note: To better illustrate what git checkout is doing, the animation goes back
    5 commits at a time.

    View Slide

  79. git bisect
    We then jump back in history (say fifteen commits at a time) until
    we find a commit without the bug.
    $ git checkout HEAD~15
    Note: To better illustrate what git checkout is doing, the animation goes back
    5 commits at a time.

    View Slide

  80. git bisect
    This commit doesn’t have the bug, so we mark it as “good” (i.e. the
    bug isn’t there).
    $ git bisect good

    View Slide

  81. git bisect
    This commit doesn’t have the bug, so we mark it as “good” (i.e. the
    bug isn’t there).
    $ git bisect good
    As soon as we do this, git automatically checks out the next com-
    mit we should test.

    View Slide

  82. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  83. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  84. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  85. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  86. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  87. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  88. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  89. git bisect
    We now continue marking commits as “good” or “bad”, and git
    immediately chooses a next possibility. . .

    View Slide

  90. git bisect
    git now reports that this commit is one that introduced the bug,
    and so it can be examined to find the source of the bug.

    View Slide

  91. git bisect
    After noting down the commit ID for later examination, you need to
    go back to where you started to carry on working. All you need to
    do is finish git bisect and perhaps run git stash pop if we
    had any stashed changes from before.
    $ git bisect reset

    View Slide

  92. git bisect
    After noting down the commit ID for later examination, you need to
    go back to where you started to carry on working. All you need to
    do is finish git bisect and perhaps run git stash pop if we
    had any stashed changes from before.
    $ git bisect reset
    Done!

    View Slide

  93. git bisect summary
    $ git bisect start
    The current commit has the bug
    $ git bisect bad
    Jump back 10 commits (repeat until good commit found)
    $ git checkout HEAD~10
    When this commit does not have the bug. ..
    $ git bisect good
    Git automatically checks out commits to test – decide if pass/fail
    $ git bisect good|bad
    Eventually git tells you which commit is bad
    Investigate...
    $ git bisect reset
    Back where you started
    work work work ...

    View Slide

  94. Questions?

    View Slide