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

Getting more from Git

Getting more from Git

I gave this talk at #FFconf in Brighton in November 2019.
This talk covers:
- What is "good" for Git?
- Why are we not very good at Git?
- A bit of history about Git. Who is she? Where did she come from?
- Some tips for using Git - --patch adding, --amending, using reset and rebase.

Alice Bartlett

November 08, 2019
Tweet

More Decks by Alice Bartlett

Other Decks in Technology

Transcript

  1. Alice Bartlett
    Principal Engineer, Customer Products team
    @alicebartlett
    Getting more
    from Git

    View Slide

  2. View Slide

  3. @alicebartlett
    This talk is about Git

    View Slide

  4. @alicebartlett
    I have some humble ambitions

    View Slide

  5. @alicebartlett
    1. Let’s all get a bit better at Git
    2. Let’s have an interesting 40 minutes

    View Slide

  6. @alicebartlett
    I think we could all do better with our
    Git mastery. To understand what “bad”
    looks like, I have found someone to
    make an example of

    View Slide

  7. @alicebartlett
    Me

    View Slide

  8. @alicebartlett
    Let’s look at my commits from
    ten years ago…

    View Slide

  9. @alicebartlett

    View Slide

  10. @alicebartlett
    This is the codebase for the FT’s web
    app. It is 9 years old, and still going
    strong.

    View Slide

  11. @alicebartlett
    204 lines of
    code added

    View Slide

  12. @alicebartlett
    and the commit
    message reads only:
    “sqlite stuff”

    View Slide

  13. @alicebartlett

    View Slide

  14. @alicebartlett
    if (false && window.history.pushState) {

    }

    View Slide

  15. @alicebartlett
    “Fixes to download”

    View Slide

  16. @alicebartlett
    ¯\_(ツ)_/¯

    View Slide

  17. @alicebartlett
    So that is what bad looks like

    View Slide

  18. @alicebartlett
    What are we aiming for?

    View Slide

  19. @alicebartlett
    1. Atomic commits
    2. Meaningful commit messages

    View Slide

  20. @alicebartlett
    What are “atomic commits”?

    View Slide

  21. @alicebartlett
    One commit per unit of change

    View Slide

  22. @alicebartlett
    A style change

    View Slide

  23. @alicebartlett
    A whitespace refactor
    A style change

    View Slide

  24. @alicebartlett
    A whitespace refactor
    A bug fix (and updated tests)
    A style change

    View Slide

  25. @alicebartlett
    A commit should be a single unit of work

    View Slide

  26. @alicebartlett
    It should make sense in isolation

    View Slide

  27. @alicebartlett
    Then your Git history becomes the story
    of your project, added to incrementally

    View Slide

  28. @alicebartlett
    The other thing is commit messages

    View Slide

  29. @alicebartlett
    Update link style
    User research showed that
    many people did not spot
    links in the copy. This
    commit updates the link style
    to the new underlined style
    which performed better.

    View Slide

  30. @alicebartlett
    // Scannable summary
    // Body that
    // explains
    // *why*
    Update link style
    User research showed that
    many people did not spot
    links in the copy. This
    commit updates the link style
    to the new underlined style
    which performed better.

    View Slide

  31. @alicebartlett
    WHY

    View Slide

  32. @alicebartlett
    Fixes to download

    View Slide

  33. @alicebartlett
    Fix background download
    There is a bug in the
    window.history.pushState
    implementation in Android Honeycomb
    so always use the location hash
    instead until that is fixed.

    View Slide

  34. 2. What is Git
    3. Tips for rewriting your Git history
    1. Why should you care

    View Slide

  35. 2. What is Git
    3. Tips for rewriting your Git history
    1. Why should you care

    View Slide

  36. @alicebartlett
    As you know, Git is a program that runs
    on your computer

    View Slide

  37. @alicebartlett
    You use it to manage the process of
    writing code

    View Slide

  38. @alicebartlett
    You use it to tell the story of your
    project

    View Slide

  39. @alicebartlett
    As engineers, there are lots of things we
    do to manage our codebases

    View Slide

  40. @alicebartlett
    1. Bikeshed over naming things

    View Slide

  41. @alicebartlett
    1. Bikeshed over naming things
    2. Write documentation

    View Slide

  42. @alicebartlett
    1. Bikeshed over naming things
    2. Write documentation
    3. Refactor

    View Slide

  43. @alicebartlett
    1. Bikeshed over naming things
    2. Write documentation
    3. Refactor
    4. Write tests
    5. … etc

    View Slide

  44. @alicebartlett
    None of these things are necessary to
    ship a feature. But they are necessary
    for helping other people understand our
    code and maintain it.

    View Slide

  45. @alicebartlett
    Git commit histories are part of
    this picture

    View Slide

  46. @alicebartlett
    Your commits, if you do them well,
    offer unique benefits over other
    ways of explaining your code:

    View Slide

  47. @alicebartlett
    1. They never change

    View Slide

  48. @alicebartlett
    1. They never change
    2. They live alongside your code

    View Slide

  49. @alicebartlett
    1. They never change
    2. They live alongside your code
    3. They’re searchable with Git grep

    View Slide

  50. @alicebartlett
    1. They never change
    2. They live alongside your code
    3. They’re searchable with Git grep
    4. They allow you to document your
    change at the time that you made it

    View Slide

  51. @alicebartlett
    1. They never change
    2. They live alongside your code
    3. They’re searchable with Git grep
    4. They allow you to document your
    change at the time that you made it
    5. They are hosting independent

    View Slide

  52. @alicebartlett
    Public Service Announcement:
    Stop putting all the information
    about a change in GitHub pull
    requests.

    View Slide

  53. @alicebartlett
    Public Service Announcement:
    Stop relying on linking to tickets for
    context.

    View Slide

  54. @alicebartlett
    PUT IT IN THE
    COMMIT
    MESSAGE

    View Slide

  55. @alicebartlett
    My second reason you should care about
    writing good commits is: it will make you
    a better software developer

    View Slide

  56. @alicebartlett
    Firstly, you’ll able to debug things
    quicker because your project will have a
    searchable history

    View Slide

  57. @alicebartlett
    Secondly, in order to write down why
    you introduced a change to a codebase,
    you have to actually understand why
    you introduced a change

    View Slide

  58. @alicebartlett
    Explaining why is an important thing to
    do as an engineer — it forces you to
    understand things you could otherwise
    have gotten away with not
    understanding

    View Slide

  59. @alicebartlett
    One of the reasons little
    baby me found writing
    good commits hard was
    that when I started
    writing code, a lot of my
    process was “try things
    until it works”

    View Slide

  60. @alicebartlett
    This meant it took me a lot longer to
    gain a deeper understanding of how
    things work

    View Slide

  61. @alicebartlett
    Taking the time to figure out why
    something works is a good investment
    in your future

    View Slide

  62. 1. Why should you care?
    • The code is better - which is better for you
    because you have to maintain it
    • It makes you smarter

    View Slide

  63. 2. What is Git
    3. Tips for rewriting your Git history
    1. Why should you care

    View Slide

  64. @alicebartlett
    Did you know that before Git, we all
    using other version control systems?

    View Slide

  65. @alicebartlett
    Linus Torvalds developed Git in 2005 to
    manage development of the Linux
    Kernel.

    View Slide

  66. @alicebartlett
    Before we get into this, let’s just talk
    about Linus.

    View Slide

  67. Alice Bartlett
    http://somewebsite.com
    Linus
    Torvalds

    View Slide

  68. @alicebartlett
    He is known for emails to the Linux mailing list
    containing comments that I don’t want to
    repeat here but they are very very unpleasant

    View Slide

  69. @alicebartlett
    Part of Linus’s personal brand is that he
    is very smart

    View Slide

  70. @alicebartlett
    When he created Git, it was described as
    a tool expressly designed to make you
    feel less intelligent than you thought you
    were

    View Slide

  71. @alicebartlett
    Up until 2005, Linux
    development had used a
    version control system
    called BitKeeper, and
    prior to that, they just
    emailed tarballs around

    View Slide

  72. @alicebartlett
    The creation of Git was a bit dramatic

    View Slide

  73. @alicebartlett
    BitKeeper was a closed source
    proprietary version control system

    View Slide

  74. @alicebartlett
    There was a free to use client, but it was
    closed source too.

    View Slide

  75. @alicebartlett
    One of the Linux contributors, Andrew
    Tridgell, decided to create an open
    source BitKeeper client as he didn’t
    think it was right to use a closed source
    client to work on an open source project

    View Slide

  76. @alicebartlett
    This upset the BitKeeper team, who
    then revoked access to their free to use
    client

    View Slide

  77. @alicebartlett
    Which meant development on the Linux
    kernel had to pause while a new version
    control system was found

    View Slide

  78. @alicebartlett
    In a talk two years later, Linus called
    Tridgell “stupid and ugly” for doing this

    View Slide

  79. @alicebartlett
    So Linus creates Git - he knows a lot
    about file system performance so he’s
    able to make it about an order of
    magnitude faster than its competitors
    across lots of operations — reading,
    committing and diffing

    View Slide

  80. @alicebartlett
    Incidentally, the version
    control system for Git is
    (obviously) Git.

    View Slide

  81. @alicebartlett
    The world’s first ever Git commit
    message is in the Git repository…

    View Slide

  82. @alicebartlett
    https://github.com/git/git/commit/
    e83c5163316f89bfbde7d9ab23ca2e25604af290
    Initial revision of
    "git", the information
    manager from hell
    Linus Torvalds, 7 Apr 2005

    View Slide

  83. @alicebartlett
    Git was a big paradigm shift

    View Slide

  84. @alicebartlett
    So much so, that thinking about how
    things used to be now is actually quite
    confusing

    View Slide

  85. @alicebartlett
    Let’s take a quick look at
    some of the ways Git was
    really different from CVS
    and Subversion, two
    popular alternatives back
    In 2005

    View Slide

  86. @alicebartlett
    One of the design choices for Git which
    is very different to its major competitors
    is that it is distributed

    View Slide

  87. @alicebartlett
    Git CVS and SVN

    View Slide

  88. @alicebartlett
    Git CVS and SVN

    View Slide

  89. @alicebartlett
    • No network connection needed

    View Slide

  90. @alicebartlett
    • No network connection needed
    • Common operations like committing are
    quicker

    View Slide

  91. @alicebartlett
    • No network connection needed
    • Common operations like committing are
    quicker
    • You can try things in private

    View Slide

  92. @alicebartlett
    • No network connection needed
    • Common operations like committing are
    quicker
    • You can try things in private
    • There is no single point of failure because
    there’s no central server

    View Slide

  93. @alicebartlett
    • No network connection needed
    • Common operations like committing are
    quicker
    • You can try things in private
    • There is no single point of failure because
    there’s no central server
    • Much easier to give people access to noodle
    around

    View Slide

  94. @alicebartlett
    Decentralised was radical at the time.

    View Slide

  95. @alicebartlett
    In 2007, Linus gave a talk at Google
    about Git and the benefits of distributed
    version control and he got about three
    questions that were all variations of…

    View Slide

  96. @alicebartlett
    “Isn’t distributed code bad actually?”

    View Slide

  97. Joel Spolksy speaking in 2010
    https://www.joelonsoftware.com/2010/03/17/distributed-version-control-is-here-to-stay-baby/
    “Possibly the biggest
    advance in software
    development
    technology in the
    [past] ten years”

    View Slide

  98. @alicebartlett
    Another thing Git does amazingly well is
    branching

    View Slide

  99. @alicebartlett
    In both CVS and SVN, branching was
    incredibly tedious

    View Slide

  100. @alicebartlett
    All branches existed in a global
    namespace, you couldn’t have a little
    private branch to do your experiments
    on

    View Slide

  101. @alicebartlett
    Branches were considered a really
    advanced technique in CVS and SVN, so
    most people just didn’t use them.

    View Slide

  102. @alicebartlett
    If you’re not using branches though
    revising your history becomes super
    annoying for your colleagues who will
    already have your first set of changes

    View Slide

  103. @alicebartlett
    If you're not using branches, and you
    only have a central repository,
    committing becomes really difficult
    because all the tests have to pass, and
    the commit must make sense in
    isolation

    View Slide

  104. @alicebartlett
    So things like atomic commits are not
    possible unless you get things right first
    time!

    View Slide

  105. @alicebartlett
    OK so — we agree:
    1. Doing version control properly is
    important
    2. Git is really good, actually.

    View Slide

  106. @alicebartlett
    Why are we so bad at Git?

    View Slide

  107. @alicebartlett
    Firstly, it is hard to use

    View Slide

  108. @alicebartlett

    View Slide

  109. @alicebartlett
    Jargon

    View Slide

  110. @alicebartlett
    Branches, commits, trees, repositories,
    working tree, staging, remotes, the
    stash, cherry picking, hunks, rebasing...

    View Slide

  111. @alicebartlett
    You are in a detached HEAD state

    View Slide

  112. @alicebartlett
    So to figure this stuff out you have to go
    read the manual. But the manual is also
    really confusing!

    View Slide

  113. @alicebartlett
    Update remote refs with
    associated changes

    View Slide

  114. @alicebartlett
    That’s the description for Git push!

    View Slide

  115. @alicebartlett
    https://git-man-page-generator.lokaltog.net/

    View Slide

  116. @alicebartlett

    View Slide

  117. @alicebartlett
    This is why we’re so bad at Git. Because
    its user interface is badly designed.

    View Slide

  118. 2. What is Git?
    • A version control system created to manage
    the Linux kernel
    • Radically different to pre-existing version
    control systems
    • Bad user interface

    View Slide

  119. 2. What is Git?
    3. Tips for rewriting your Git history
    1. Why should you care

    View Slide

  120. @alicebartlett
    Here is what we’re aiming for...

    View Slide

  121. @alicebartlett
    1. Atomic commits
    2. Meaningful commit messages

    View Slide

  122. @alicebartlett
    Start End

    View Slide

  123. @alicebartlett
    Start End
    Start End

    View Slide

  124. @alicebartlett
    1.git add --patch
    2.git commit --amend
    3.git reset [sha]

    View Slide

  125. @alicebartlett
    Unfortunately I’m going to have to
    explain some jargon here…

    View Slide

  126. @alicebartlett
    In Git there are three data structures
    that represent your work

    View Slide

  127. @alicebartlett
    // Working directory

    View Slide

  128. @alicebartlett
    // Working directory
    // Staging index

    View Slide

  129. @alicebartlett
    // Working directory
    // Staging index
    // Commit history

    View Slide

  130. @alicebartlett
    Every commit has a
    parent which it points to

    View Slide

  131. @alicebartlett
    git add
    git add --patch

    View Slide

  132. @alicebartlett
    Before you can commit something, you
    have to add it to the list of things you
    want to commit.

    View Slide

  133. @alicebartlett
    In git jargon you “stage” it by using git add

    View Slide

  134. @alicebartlett
    // Working directory
    // Staging index
    // Commit history

    View Slide

  135. @alicebartlett

    View Slide

  136. @alicebartlett
    $ git add

    View Slide

  137. @alicebartlett
    $ git commit

    View Slide

  138. @alicebartlett
    $ git commit -am "sqlite stuff"

    View Slide

  139. @alicebartlett
    When you have some lines in your file
    that you want to commit but some that
    you don’t — use git add --patch

    View Slide

  140. @alicebartlett
    Using git add --patch means that
    even if you’ve failed to work atomically,
    ie you have ended up with multiple
    changes in the same file, you can still
    commit atomically

    View Slide

  141. @alicebartlett
    Start End
    Start End

    View Slide

  142. @alicebartlett
    git add --patch will ask you which
    bits of a file you want to add. It calls
    these “bits” hunks.

    View Slide

  143. $ git add --patch

    View Slide

  144. $ git add --patch
    diff --git a/config/playlist.js b/config/playlist.js
    index 7e54d1a..eba4bf5 100644
    --- a/config/playlist.js
    +++ b/config/playlist.js
    @@ -28,14 +28,6 @@ const playlistConfigs = {
    videos: byDuration
    })
    },
    - popular: {
    - query: queries['popular-videos'],
    - dataReader: ({ data: { video: { popular = []}} = {}} = {}) => ({
    - videos: popular
    - })
    - },
    section: {
    query: queries['section-videos'],
    dataReader: ({ data: { section = {}} = {}} = {}) => {
    Stage this hunk [y,n,q,s,e,?]?

    View Slide

  145. $ git add --patch
    diff --git a/config/playlist.js b/config/playlist.js
    index 7e54d1a..eba4bf5 100644
    --- a/config/playlist.js
    +++ b/config/playlist.js
    @@ -28,14 +28,6 @@ const playlistConfigs = {
    videos: byDuration
    })
    },
    - popular: {
    - query: queries['popular-videos'],
    - dataReader: ({ data: { video: { popular = []}} = {}} = {}) => ({
    - videos: popular
    - })
    - },
    section: {
    query: queries['section-videos'],
    dataReader: ({ data: { section = {}} = {}} = {}) => {
    Stage this hunk [y,n,q,s,e,?]?
    Nice diff of
    your changes

    View Slide

  146. $ git add --patch
    diff --git a/config/playlist.js b/config/playlist.js
    index 7e54d1a..eba4bf5 100644
    --- a/config/playlist.js
    +++ b/config/playlist.js
    @@ -28,14 +28,6 @@ const playlistConfigs = {
    videos: byDuration
    })
    },
    - popular: {
    - query: queries['popular-videos'],
    - dataReader: ({ data: { video: { popular = []}} = {}} = {}) => ({
    - videos: popular
    - })
    - },
    section: {
    query: queries['section-videos'],
    dataReader: ({ data: { section = {}} = {}} = {}) => {
    Stage this hunk [y,n,q,s,e,?]?

    View Slide

  147. @alicebartlett
    Stage this hunk [y,n,q,s,e,?]?

    View Slide

  148. @alicebartlett
    Stage this hunk [y,n,q,s,e,?]?
    y: yes add this to the things I want to commit
    n: no, leave this hunk alone
    q: quit
    s: split this hunk into smaller hunks
    e: manually edit the hunk
    ?: tell me about these options

    View Slide

  149. @alicebartlett
    Stage this hunk [y,n,q,s,e,?]?
    y: yes add this to the things I want to commit
    n: no, leave this hunk alone
    q: quit
    s: split this hunk into smaller hunks
    e: manually edit the hunk
    ?: tell me about these options

    View Slide

  150. @alicebartlett
    git commit --amend

    View Slide

  151. @alicebartlett
    So git commit is something you’ll have
    used many times if you’ve used git.
    git commit --amend lets you amend
    your last commit.

    View Slide

  152. @alicebartlett
    Super useful if you committed too soon, or
    you want to modify the commit message

    View Slide

  153. @alicebartlett
    When you use git commit --amend you
    completely replace the last commit with a
    new one and it will commit everything
    that’s currently staged.

    View Slide

  154. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS

    View Slide

  155. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS
    oops :(

    View Slide

  156. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS
    $ git commit --amend

    View Slide

  157. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS
    $ git commit --amend
    439301fe69e8f875c049ad0718386516b4878e22
    20-05-2016: Fix broken sign up button CSS

    View Slide

  158. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS
    439301fe69e8f875c049ad0718386516b4878e22
    20-05-2016: Fix broken sign up button CSS

    View Slide

  159. 377dfcd00dd057542b112cf13be6cf1380b292ad
    20-05-2016: Fix broken sign up buttno CSS
    439301fe69e8f875c049ad0718386516b4878e22
    20-05-2016: Fix broken sign up button CSS

    View Slide

  160. @alicebartlett
    git reset

    View Slide

  161. @alicebartlett
    Use git reset when you want to undo
    changes

    View Slide

  162. @alicebartlett
    $ git commit
    $ git add

    View Slide

  163. @alicebartlett
    git reset moves
    changes back
    through these
    structures
    What gets moved
    depends on the
    arguments you call
    reset with

    View Slide

  164. @alicebartlett
    Calling git reset with no
    additional arguments moves
    any changes on the Staging
    Index back to the Working
    Directory.
    Nothing happens to the
    commit history.
    git reset

    View Slide

  165. @alicebartlett
    Calling git reset will
    move all changes from any
    commit after the id you’ve
    given it back to the Working
    Directory
    git reset

    View Slide

  166. @alicebartlett
    Calling git reset will
    move all changes from any
    commit after the id you’ve
    given it back to the Working
    Directory
    git reset
    Commit

    View Slide

  167. @alicebartlett
    You can also call git reset with the
    --hard option.
    This will reset the pointers to
    commit and DELETE the
    contents of you working Directory.
    Any uncommitted changes in your
    working directory or staging index
    are lost
    git reset --hard

    View Slide

  168. @alicebartlett
    You can also call git reset with the
    --hard option.
    This will reset the pointers to
    commit and DELETE the
    contents of you working Directory.
    Any uncommitted changes in your
    working directory or staging index
    are lost
    git reset --hard
    Gone!

    View Slide

  169. @alicebartlett
    1. git add and git add --patch to selectively move
    changes from Working Directory to Staging
    2. git commit --amend to quickly change commit messages
    3. git reset to move work backwards in workflow

    View Slide

  170. @alicebartlett
    1.git rebase
    2.git rebase --interactive

    View Slide

  171. @alicebartlett
    Start End
    Start End
    In the last bit we covered making and undoing
    commits, now we’re going to look at changing
    larger bits of your commit history

    View Slide

  172. @alicebartlett
    git rebase allows you to literally
    rewrite your history. This is very useful
    as often, through making changes, new
    or better ways of doing things or
    ordering changes reveal themselves

    View Slide

  173. @alicebartlett
    Rebasing replays your changes over a
    branch.
    You take the patch of one commit and
    apply it to a different commit

    View Slide

  174. @alicebartlett
    feature branch
    master
    Rebasing is changing the
    base of your branch from
    one commit to another,
    making it look as if you had
    created a branch from a
    different commit
    HEAD

    View Slide

  175. @alicebartlett
    feature branch
    master

    View Slide

  176. @alicebartlett
    feature branch
    master

    View Slide

  177. @alicebartlett
    feature branch
    master
    HEAD

    View Slide

  178. @alicebartlett
    feature branch
    (merge commit)
    master
    feature branch
    master
    Rebase
    Merge

    View Slide

  179. @alicebartlett
    feature branch
    If you're working on a feature and want to bring in
    changes from master that happen in the interim,
    rebasing stops you from having lots of merge commits
    merge commit

    View Slide

  180. @alicebartlett
    The golden rule of rebasing is:
    ONLY USE IT ON LOCAL UNPUBLISHED
    BRANCHES

    View Slide

  181. @alicebartlett
    1.git rebase
    2.git rebase --interactive

    View Slide

  182. @alicebartlett
    Rebasing on it’s own is kind of
    interesting, but the really useful stuff
    happens with
    git rebase --interactive

    View Slide

  183. @alicebartlett
    git rebase --interactive takes
    rebasing and turns it into a very boring
    text adventure game

    View Slide

  184. @alicebartlett
    On the feature branch and we run:
    git rebase --interactive origin/master
    feature branch
    master

    View Slide

  185. @alicebartlett
    So - we’re going to replay these
    commits here: feature branch
    master

    View Slide

  186. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    pick 637bf758 Add commentwer mock
    pick fb274f86 Whitespace
    # Rebase 66d43b29..fb274f86 onto 66d43b29 (5 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    # l, label = label current HEAD with a name
    # t, reset = reset HEAD to a label
    # m, merge [-C | -c ] [# ]
    #
    # [… etc… ]

    View Slide

  187. @alicebartlett
    A list of
    commits
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    pick 637bf758 Add commentwer mock
    pick fb274f86 Whitespace
    # Rebase 66d43b29..fb274f86 onto 66d43b29 (5 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    # l, label = label current HEAD with a name
    # t, reset = reset HEAD to a label
    # m, merge [-C | -c ] [# ]
    #
    # [… etc… ]

    View Slide

  188. @alicebartlett
    A list of
    commands
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    pick 637bf758 Add commentwer mock
    pick fb274f86 Whitespace
    # Rebase 66d43b29..fb274f86 onto 66d43b29 (5 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    # l, label = label current HEAD with a name
    # t, reset = reset HEAD to a label
    # m, merge [-C | -c ] [# ]
    #
    # [… etc… ]

    View Slide

  189. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    pick 637bf758 Add commentwer mock
    pick fb274f86 Whitespace
    Lets merge these two
    commits as they’re
    both just whitespace
    changes

    View Slide

  190. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    pick 637bf758 Add commentwer mock
    We can use “squash”
    to do that

    View Slide

  191. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    pick 637bf758 Add commentwer mock
    Let’s also fix this typo
    using the re-word option

    View Slide

  192. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock
    Let’s also fix this typo
    using the re-word option

    View Slide

  193. @alicebartlett
    Once you close that rebase file Git will
    step you through each of the commands
    from top to bottom, stopping when your
    input is required

    View Slide

  194. @alicebartlett
    feature
    HEAD
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock

    View Slide

  195. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock
    pick
    feature
    HEAD

    View Slide

  196. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock
    pick
    feature
    HEAD

    View Slide

  197. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock
    squash
    feature
    HEAD

    View Slide

  198. @alicebartlett
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commentwer mock
    reword
    feature
    HEAD

    View Slide

  199. @alicebartlett
    feature
    HEAD
    pick a8f83c27 Remove CommentFactory documentation
    pick cf19c147 Whitespace changes
    squash fb274f86 Whitespace
    reword 637bf758 Add commenter mock

    View Slide

  200. @alicebartlett
    OK — time for a more complicated
    rebase example...

    View Slide

  201. @alicebartlett
    This is about the nursery rhyme
    “Old Mac Donald”

    View Slide

  202. @alicebartlett
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    and on that farm he had some cows
    eee-eye-eee-eye-oh!
    With a moo moo here!
    and a moo moo there!
    here a moo!
    there a moo!
    everywhere a moo moo!
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh

    View Slide

  203. @alicebartlett
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    and on that farm he had some cows
    eee-eye-eee-eye-oh!
    With a moo moo here!
    and a moo moo there!
    here a moo!
    there a moo!
    everywhere a moo moo!
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    Initial commit

    View Slide

  204. @alicebartlett
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    and on that farm she had some cows
    eee-eye-eee-eye-oh!
    With a moo moo here!
    and a moo moo there!
    here a moo!
    there a moo!
    everywhere a moo moo!
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    Initial commit
    Change gender"

    View Slide

  205. @alicebartlett
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    and on that farm she had some wheat
    eee-eye-eee-eye-oh!
    With a swish swish here!
    and a swish swish there!
    here a swish!
    there a swish!
    everywhere a swish swish!
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    Initial commit
    Change gender"
    Farm wheat

    View Slide

  206. @alicebartlett
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    and on that farm they had some wheat
    eee-eye-eee-eye-oh!
    With a swish swish here!
    and a swish swish there!
    here a swish!
    there a swish!
    everywhere a swish swish!
    Old Mac Donald had a farm
    eee-eye-eee-eye-oh
    Initial commit
    Change gender"
    Farm wheat
    Use singular they

    View Slide

  207. @alicebartlett
    Initial commit
    Change gender"
    Farm wheat
    Use singular they
    Let’s delete this
    from commit. We
    don't need it, it
    doesn’t help tell the
    story of our project

    View Slide

  208. @alicebartlett
    $ git rebase -i HEAD~4

    View Slide

  209. @alicebartlett
    pick a Initial commit
    pick b Change gender "
    pick c Farm wheat
    pick d Use singular they
    Initial commit
    Change gender"
    Farm wheat
    Use singular they

    View Slide

  210. @alicebartlett
    Initial commit
    Change gender"
    Farm wheat
    Use singular they
    pick a Initial commit
    pick c Farm wheat
    pick d Use singular they

    View Slide

  211. @alicebartlett
    Auto-merging old-mac-donald.txt
    CONFLICT (content): Merge conflict in old-mac-donald.txt
    error: could not apply C... Farm wheat
    Resolve all conflicts manually, mark them as resolved with
    "git add/rm ", then run "git rebase --continue".
    You can instead skip this commit: run "git rebase --skip".
    To abort and get back to the state before "git rebase", run "git
    rebase --abort".
    Could not apply C... Farm wheat

    View Slide

  212. MERGE
    CONFLICT!!!

    View Slide

  213. @alicebartlett
    $ git rebase --abort

    View Slide

  214. @alicebartlett
    Auto-merging old-mac-donald.txt
    CONFLICT (content): Merge conflict in old-mac-
    donald.txt
    error: could not apply C... Farm wheat
    Resolve all conflicts manually, mark them as
    resolved with
    "git add/rm ", then run "git
    rebase --continue".
    You can instead skip this commit: run "git rebase
    --skip".
    To abort and get back to the state before "git
    rebase", run "git rebase --abort".
    Could not apply C... Farm wheat
    Initial commit
    Change gender"
    Farm wheat
    Use singular they

    View Slide

  215. @alicebartlett
    Why has
    this happened?
    Initial commit
    Change gender"
    Farm wheat
    Use singular they

    View Slide

  216. @alicebartlett
    Initial commit
    Change gender"
    Farm wheat
    Use singular they
    We deleted our
    “Change gender”
    commit

    View Slide

  217. @alicebartlett
    Initial commit
    Change gender"
    Farm wheat
    Use singular they
    But our “Farm wheat”
    change expected it

    View Slide

  218. @alicebartlett
    $ git show b
    commit b
    [...]
    eee-eye-eee-eye-oh
    -and on that farm he had some cows
    +and on that farm she had some cows
    eee-eye-eee-eye-oh!
    [...]

    View Slide

  219. @alicebartlett
    $ git show c
    commit c
    [...]
    eee-eye-eee-eye-oh
    -and on that farm she had some cows
    +and on that farm she had some wheat
    eee-eye-eee-eye-oh!
    [...]

    View Slide

  220. @alicebartlett
    eee-eye-eee-eye-oh
    <<<<<<< HEAD
    and on that farm he had some cows
    =======
    and on that farm she had some wheat
    >>>>>>> c... Switch to wheat
    eee-eye-eee-eye-oh!

    View Slide

  221. @alicebartlett
    eee-eye-eee-eye-oh
    and on that farm he had some wheat
    eee-eye-eee-eye-oh!

    View Slide

  222. @alicebartlett
    eee-eye-eee-eye-oh
    and on that farm he had some wheat
    eee-eye-eee-eye-oh!
    And now we’re good to go — we can
    add that change and continue run
    git rebase --continue

    View Slide

  223. @alicebartlett
    And you have single handedly
    saved the planet and destroyed the
    gender binary in a two commit
    messages while also overcoming a
    merge conflict and maintaining a
    clean Git history. Not bad.
    Initial commit
    Farm wheat
    Use singular they

    View Slide

  224. @alicebartlett
    1. git rebase to pull in any changes from another branch for
    a neater history without any merge commits
    2. git rebase --interactive to edit and restructure
    multiple commits before you push them

    View Slide

  225. 3. Tips for Git history management
    • Use git add --patch to help iron out your
    messy working process from the history
    • Gateway drug: git commit --amend
    • Use git reset to undo things in the history
    • Use git rebase for redo things in the history

    View Slide

  226. 2. What is Git
    3. Tips for rewriting your Git history
    1. Why should you care

    View Slide

  227. @alicebartlett
    Start End
    Start End

    View Slide

  228. @alicebartlett
    Thank you
    @alicebartlett

    View Slide

  229. @alicebartlett
    1. Noun Project Faces by Sarah Rudkin: https://
    thenounproject.com/sarahdrudkin/collection/faces/
    2. Linus Torvalds at Google 2007: https://www.youtube.com/
    watch?v=4XpnKHJAok8
    3. Tekin Süleyman’s A Branch In Time: https://
    www.youtube.com/watch?v=1NoNTqank_U
    4. Git man page generator: https://git-man-page-
    generator.lokaltog.net/

    View Slide