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.

Df057cdadda4cd7a2a2db52576de1bf2?s=128

Alice Bartlett

November 08, 2019
Tweet

Transcript

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

    from Git
  2. None
  3. @alicebartlett This talk is about Git

  4. @alicebartlett I have some humble ambitions

  5. @alicebartlett 1. Let’s all get a bit better at Git

    2. Let’s have an interesting 40 minutes
  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
  7. @alicebartlett Me

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

  9. @alicebartlett

  10. @alicebartlett This is the codebase for the FT’s web app.

    It is 9 years old, and still going strong.
  11. @alicebartlett 204 lines of code added

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

  13. @alicebartlett

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

  15. @alicebartlett “Fixes to download”

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

  17. @alicebartlett So that is what bad looks like

  18. @alicebartlett What are we aiming for?

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

  20. @alicebartlett What are “atomic commits”?

  21. @alicebartlett One commit per unit of change

  22. @alicebartlett A style change

  23. @alicebartlett A whitespace refactor A style change

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

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

  26. @alicebartlett It should make sense in isolation

  27. @alicebartlett Then your Git history becomes the story of your

    project, added to incrementally
  28. @alicebartlett The other thing is commit messages

  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.
  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.
  31. @alicebartlett WHY

  32. @alicebartlett Fixes to download

  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.
  34. 2. What is Git 3. Tips for rewriting your Git

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

    history 1. Why should you care
  36. @alicebartlett As you know, Git is a program that runs

    on your computer
  37. @alicebartlett You use it to manage the process of writing

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

    project
  39. @alicebartlett As engineers, there are lots of things we do

    to manage our codebases
  40. @alicebartlett 1. Bikeshed over naming things

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

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

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

    Refactor 4. Write tests 5. … etc
  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.
  45. @alicebartlett Git commit histories are part of this picture

  46. @alicebartlett Your commits, if you do them well, offer unique

    benefits over other ways of explaining your code:
  47. @alicebartlett 1. They never change

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

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

    code 3. They’re searchable with Git grep
  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
  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
  52. @alicebartlett Public Service Announcement: Stop putting all the information about

    a change in GitHub pull requests.
  53. @alicebartlett Public Service Announcement: Stop relying on linking to tickets

    for context.
  54. @alicebartlett PUT IT IN THE COMMIT MESSAGE

  55. @alicebartlett My second reason you should care about writing good

    commits is: it will make you a better software developer
  56. @alicebartlett Firstly, you’ll able to debug things quicker because your

    project will have a searchable history
  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
  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
  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”
  60. @alicebartlett This meant it took me a lot longer to

    gain a deeper understanding of how things work
  61. @alicebartlett Taking the time to figure out why something works

    is a good investment in your future
  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
  63. 2. What is Git 3. Tips for rewriting your Git

    history 1. Why should you care
  64. @alicebartlett Did you know that before Git, we all using

    other version control systems?
  65. @alicebartlett Linus Torvalds developed Git in 2005 to manage development

    of the Linux Kernel.
  66. @alicebartlett Before we get into this, let’s just talk about

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

  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
  69. @alicebartlett Part of Linus’s personal brand is that he is

    very smart
  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
  71. @alicebartlett Up until 2005, Linux development had used a version

    control system called BitKeeper, and prior to that, they just emailed tarballs around
  72. @alicebartlett The creation of Git was a bit dramatic

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

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

    was closed source too.
  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
  76. @alicebartlett This upset the BitKeeper team, who then revoked access

    to their free to use client
  77. @alicebartlett Which meant development on the Linux kernel had to

    pause while a new version control system was found
  78. @alicebartlett In a talk two years later, Linus called Tridgell

    “stupid and ugly” for doing this
  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
  80. @alicebartlett Incidentally, the version control system for Git is (obviously)

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

    the Git repository…
  82. @alicebartlett https://github.com/git/git/commit/ e83c5163316f89bfbde7d9ab23ca2e25604af290 Initial revision of "git", the information manager

    from hell Linus Torvalds, 7 Apr 2005
  83. @alicebartlett Git was a big paradigm shift

  84. @alicebartlett So much so, that thinking about how things used

    to be now is actually quite confusing
  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
  86. @alicebartlett One of the design choices for Git which is

    very different to its major competitors is that it is distributed
  87. @alicebartlett Git CVS and SVN

  88. @alicebartlett Git CVS and SVN

  89. @alicebartlett • No network connection needed

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

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

    committing are quicker • You can try things in private
  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
  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
  94. @alicebartlett Decentralised was radical at the time.

  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…
  96. @alicebartlett “Isn’t distributed code bad actually?”

  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”
  98. @alicebartlett Another thing Git does amazingly well is branching

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

  100. @alicebartlett All branches existed in a global namespace, you couldn’t

    have a little private branch to do your experiments on
  101. @alicebartlett Branches were considered a really advanced technique in CVS

    and SVN, so most people just didn’t use them.
  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
  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
  104. @alicebartlett So things like atomic commits are not possible unless

    you get things right first time!
  105. @alicebartlett OK so — we agree: 1. Doing version control

    properly is important 2. Git is really good, actually.
  106. @alicebartlett Why are we so bad at Git?

  107. @alicebartlett Firstly, it is hard to use

  108. @alicebartlett

  109. @alicebartlett Jargon

  110. @alicebartlett Branches, commits, trees, repositories, working tree, staging, remotes, the

    stash, cherry picking, hunks, rebasing...
  111. @alicebartlett You are in a detached HEAD state

  112. @alicebartlett So to figure this stuff out you have to

    go read the manual. But the manual is also really confusing!
  113. @alicebartlett Update remote refs with associated changes

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

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

  116. @alicebartlett

  117. @alicebartlett This is why we’re so bad at Git. Because

    its user interface is badly designed.
  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
  119. 2. What is Git? 3. Tips for rewriting your Git

    history 1. Why should you care
  120. @alicebartlett Here is what we’re aiming for...

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

  122. @alicebartlett Start End

  123. @alicebartlett Start End Start End

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

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

    here…
  126. @alicebartlett In Git there are three data structures that represent

    your work
  127. @alicebartlett // Working directory

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

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

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

  131. @alicebartlett git add git add --patch

  132. @alicebartlett Before you can commit something, you have to add

    it to the list of things you want to commit.
  133. @alicebartlett In git jargon you “stage” it by using git

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

  135. @alicebartlett

  136. @alicebartlett $ git add

  137. @alicebartlett $ git commit

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

  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
  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
  141. @alicebartlett Start End Start End

  142. @alicebartlett git add --patch will ask you which bits of

    a file you want to add. It calls these “bits” hunks.
  143. $ git add --patch

  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,?]?
  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
  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,?]?
  147. @alicebartlett Stage this hunk [y,n,q,s,e,?]?

  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
  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
  150. @alicebartlett git commit --amend

  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.
  152. @alicebartlett Super useful if you committed too soon, or you

    want to modify the commit message
  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.
  154. 377dfcd00dd057542b112cf13be6cf1380b292ad 20-05-2016: Fix broken sign up buttno CSS

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

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

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

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

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

    Fix broken sign up button CSS
  160. @alicebartlett git reset

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

  162. @alicebartlett $ git commit $ git add

  163. @alicebartlett git reset moves changes back through these structures What

    gets moved depends on the arguments you call reset with
  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
  165. @alicebartlett Calling git reset <sha> will move all changes from

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

    any commit after the id you’ve given it back to the Working Directory git reset <sha> Commit <sha>
  167. @alicebartlett You can also call git reset with the --hard

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

    option. This will reset the pointers to commit <sha> and DELETE the contents of you working Directory. Any uncommitted changes in your working directory or staging index are lost git reset <sha> --hard Gone!
  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
  170. @alicebartlett 1.git rebase 2.git rebase --interactive

  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
  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
  173. @alicebartlett Rebasing replays your changes over a branch. You take

    the patch of one commit and apply it to a different commit
  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
  175. @alicebartlett feature branch master

  176. @alicebartlett feature branch master

  177. @alicebartlett feature branch master HEAD

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

    Merge
  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
  180. @alicebartlett The golden rule of rebasing is: ONLY USE IT

    ON LOCAL UNPUBLISHED BRANCHES
  181. @alicebartlett 1.git rebase 2.git rebase --interactive

  182. @alicebartlett Rebasing on it’s own is kind of interesting, but

    the really useful stuff happens with git rebase --interactive
  183. @alicebartlett git rebase --interactive takes rebasing and turns it into

    a very boring text adventure game
  184. @alicebartlett On the feature branch and we run: git rebase

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

    feature branch master
  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 <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # # [… etc… ]
  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 <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # # [… etc… ]
  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 <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # # [… etc… ]
  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
  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
  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
  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
  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
  194. @alicebartlett feature HEAD pick a8f83c27 Remove CommentFactory documentation pick cf19c147

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

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

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

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

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

    Whitespace changes squash fb274f86 Whitespace reword 637bf758 Add commenter mock
  200. @alicebartlett OK — time for a more complicated rebase example...

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

  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
  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
  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"
  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
  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
  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
  208. @alicebartlett $ git rebase -i HEAD~4

  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
  210. @alicebartlett Initial commit Change gender" Farm wheat Use singular they

    pick a Initial commit pick c Farm wheat pick d Use singular they
  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 <conflicted_files>", 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
  212. MERGE CONFLICT!!!

  213. @alicebartlett $ git rebase --abort

  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 <conflicted_files>", 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
  215. @alicebartlett Why has this happened? Initial commit Change gender" Farm

    wheat Use singular they
  216. @alicebartlett Initial commit Change gender" Farm wheat Use singular they

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

    But our “Farm wheat” change expected it
  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! [...]
  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! [...]
  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!
  221. @alicebartlett eee-eye-eee-eye-oh and on that farm he had some wheat

    eee-eye-eee-eye-oh!
  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
  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
  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
  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
  226. 2. What is Git 3. Tips for rewriting your Git

    history 1. Why should you care
  227. @alicebartlett Start End Start End

  228. @alicebartlett Thank you @alicebartlett

  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/