Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

@alicebartlett This talk is about Git

Slide 4

Slide 4 text

@alicebartlett I have some humble ambitions

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

@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

Slide 7

Slide 7 text

@alicebartlett Me

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

@alicebartlett

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

@alicebartlett 204 lines of code added

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

@alicebartlett

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

@alicebartlett “Fixes to download”

Slide 16

Slide 16 text

@alicebartlett ¯\_(ツ)_/¯

Slide 17

Slide 17 text

@alicebartlett So that is what bad looks like

Slide 18

Slide 18 text

@alicebartlett What are we aiming for?

Slide 19

Slide 19 text

@alicebartlett 1. Atomic commits 2. Meaningful commit messages

Slide 20

Slide 20 text

@alicebartlett What are “atomic commits”?

Slide 21

Slide 21 text

@alicebartlett One commit per unit of change

Slide 22

Slide 22 text

@alicebartlett A style change

Slide 23

Slide 23 text

@alicebartlett A whitespace refactor A style change

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

@alicebartlett A commit should be a single unit of work

Slide 26

Slide 26 text

@alicebartlett It should make sense in isolation

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

@alicebartlett The other thing is commit messages

Slide 29

Slide 29 text

@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.

Slide 30

Slide 30 text

@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.

Slide 31

Slide 31 text

@alicebartlett WHY

Slide 32

Slide 32 text

@alicebartlett Fixes to download

Slide 33

Slide 33 text

@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.

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

@alicebartlett 1. Bikeshed over naming things

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

@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.

Slide 45

Slide 45 text

@alicebartlett Git commit histories are part of this picture

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

@alicebartlett 1. They never change

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

@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

Slide 51

Slide 51 text

@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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

@alicebartlett PUT IT IN THE COMMIT MESSAGE

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

@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

Slide 58

Slide 58 text

@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

Slide 59

Slide 59 text

@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”

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

Alice Bartlett http://somewebsite.com Linus Torvalds

Slide 68

Slide 68 text

@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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

@alicebartlett The creation of Git was a bit dramatic

Slide 73

Slide 73 text

@alicebartlett BitKeeper was a closed source proprietary version control system

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

@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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

@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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

@alicebartlett Git was a big paradigm shift

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

@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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

@alicebartlett Git CVS and SVN

Slide 88

Slide 88 text

@alicebartlett Git CVS and SVN

Slide 89

Slide 89 text

@alicebartlett • No network connection needed

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

@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

Slide 93

Slide 93 text

@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

Slide 94

Slide 94 text

@alicebartlett Decentralised was radical at the time.

Slide 95

Slide 95 text

@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…

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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”

Slide 98

Slide 98 text

@alicebartlett Another thing Git does amazingly well is branching

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

@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

Slide 103

Slide 103 text

@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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

@alicebartlett Why are we so bad at Git?

Slide 107

Slide 107 text

@alicebartlett Firstly, it is hard to use

Slide 108

Slide 108 text

@alicebartlett

Slide 109

Slide 109 text

@alicebartlett Jargon

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

@alicebartlett You are in a detached HEAD state

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

@alicebartlett Update remote refs with associated changes

Slide 114

Slide 114 text

@alicebartlett That’s the description for Git push!

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

@alicebartlett

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

@alicebartlett 1. Atomic commits 2. Meaningful commit messages

Slide 122

Slide 122 text

@alicebartlett Start End

Slide 123

Slide 123 text

@alicebartlett Start End Start End

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

@alicebartlett // Working directory

Slide 128

Slide 128 text

@alicebartlett // Working directory // Staging index

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

@alicebartlett Every commit has a parent which it points to

Slide 131

Slide 131 text

@alicebartlett git add git add --patch

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

@alicebartlett

Slide 136

Slide 136 text

@alicebartlett $ git add

Slide 137

Slide 137 text

@alicebartlett $ git commit

Slide 138

Slide 138 text

@alicebartlett $ git commit -am "sqlite stuff"

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

@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

Slide 141

Slide 141 text

@alicebartlett Start End Start End

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

$ git add --patch

Slide 144

Slide 144 text

$ 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,?]?

Slide 145

Slide 145 text

$ 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

Slide 146

Slide 146 text

$ 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,?]?

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

@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

Slide 149

Slide 149 text

@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

Slide 150

Slide 150 text

@alicebartlett git commit --amend

Slide 151

Slide 151 text

@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.

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

@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.

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

@alicebartlett git reset

Slide 161

Slide 161 text

@alicebartlett Use git reset when you want to undo changes

Slide 162

Slide 162 text

@alicebartlett $ git commit $ git add

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

@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

Slide 165

Slide 165 text

@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

Slide 166

Slide 166 text

@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

Slide 167

Slide 167 text

@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

Slide 168

Slide 168 text

@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!

Slide 169

Slide 169 text

@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

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

@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

Slide 172

Slide 172 text

@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

Slide 173

Slide 173 text

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

Slide 174

Slide 174 text

@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

Slide 175

Slide 175 text

@alicebartlett feature branch master

Slide 176

Slide 176 text

@alicebartlett feature branch master

Slide 177

Slide 177 text

@alicebartlett feature branch master HEAD

Slide 178

Slide 178 text

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

Slide 179

Slide 179 text

@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

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

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

Slide 183

Slide 183 text

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

Slide 184

Slide 184 text

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

Slide 185

Slide 185 text

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

Slide 186

Slide 186 text

@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… ]

Slide 187

Slide 187 text

@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… ]

Slide 188

Slide 188 text

@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… ]

Slide 189

Slide 189 text

@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

Slide 190

Slide 190 text

@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

Slide 191

Slide 191 text

@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

Slide 192

Slide 192 text

@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

Slide 193

Slide 193 text

@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

Slide 194

Slide 194 text

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

Slide 195

Slide 195 text

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

Slide 196

Slide 196 text

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

Slide 197

Slide 197 text

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

Slide 198

Slide 198 text

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

Slide 199

Slide 199 text

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

Slide 200

Slide 200 text

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

Slide 201

Slide 201 text

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

Slide 202

Slide 202 text

@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

Slide 203

Slide 203 text

@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

Slide 204

Slide 204 text

@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"

Slide 205

Slide 205 text

@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

Slide 206

Slide 206 text

@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

Slide 207

Slide 207 text

@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

Slide 208

Slide 208 text

@alicebartlett $ git rebase -i HEAD~4

Slide 209

Slide 209 text

@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

Slide 210

Slide 210 text

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

Slide 211

Slide 211 text

@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

Slide 212

Slide 212 text

MERGE CONFLICT!!!

Slide 213

Slide 213 text

@alicebartlett $ git rebase --abort

Slide 214

Slide 214 text

@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

Slide 215

Slide 215 text

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

Slide 216

Slide 216 text

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

Slide 217

Slide 217 text

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

Slide 218

Slide 218 text

@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! [...]

Slide 219

Slide 219 text

@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! [...]

Slide 220

Slide 220 text

@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!

Slide 221

Slide 221 text

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

Slide 222

Slide 222 text

@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

Slide 223

Slide 223 text

@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

Slide 224

Slide 224 text

@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

Slide 225

Slide 225 text

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

Slide 226

Slide 226 text

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

Slide 227

Slide 227 text

@alicebartlett Start End Start End

Slide 228

Slide 228 text

@alicebartlett Thank you @alicebartlett

Slide 229

Slide 229 text

@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/