Documentation Tradeoffs and Why Commit Messages are Worth Spending Time On
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Rothmeier, Greggory
We've all thought "what is this thing supposed to do?" or "why was this done that way" moment when looking through codebases and unless there's documentation or you can find the author, the answer is often hard to find. There are many options to document code from comments to internal wikis, so I'll discuss a heuristic for evaluating the options based on the accessibility (how far away is the answer?) and accuracy (how likely is it that what I'm reading is out of date?) to build a case that the git commit message is likely where you should spend your energy documenting.
 Thanks for everyone for joining me in this discussion. Today I want to talk about Git, commit messages, and some unexpected value that they can provide as a form of documentation. Starting out, I want to talk about complexity. I started a stitch fix a little bit over a year ago, and we have pretty good onboard documentation. I read the Wiki, I read your first day, got my computer set up, and I felt like I had a pretty good sense of the teams and the apps. Then the rubber met the road and I got my first story. My team works on an application that's been around for about six years now. It's accrued a lot of complexity. So add to this, the first story I took was a bug fix. So as I got into it, this is just what it felt like. I felt like I was dealing with a lot of different pieces and they're connected to each other, but it wasn't exactly clear why or how they're connected or when I'm changing something here, what's going to happen elsewhere. And so it got me thinking about documentation and where I could look for the answers to this question. And two different metrics stand out for me as a way of thinking about my documentation. Accuracy and accessibility. So accessibility to me means that I don't have to work too hard to get it. If I have to look at documentation often throughout the day, if it takes me a minute to find an answer, and I'm doing that a couple dozen times, that's 30 minutes. It really adds up. And so if I can get an answer quickly in a few seconds, that's perfect. If I don't have to read my text editor, that's even better. Accuracy is kind of like what it sounds like. It's a sense of, is the information I'm reading, is it correct? Or has something changed? Has the code evolved in a way that is separate from the documentation and now what I'm reading about it is incorrect? So one of the ways we can get answers is with, my phone will connect. All right, we're going to do it this way. It's with wikis. So this is how I started, we're going to get all the transitions now. Wikis are great for the onboarding stuff, the new hire, the high level. You're not going to change it very often. But you see, I put it down here in this bottom left because they're not super accessible. Yes, you can search some, but for me, in my experience, the search just never seems to work as like I want. I always have a hard time. And they're not always accurate. So for new hire stuff, they're good. But if you were to try to document that circuit diagram, that entire system in a wiki, it would just very quickly go out of date. Next is JIRA. So issue tracker is maybe use pivotal tracker. We use JIRA at Stitch Fix. And I can look at recent issues and try to get a sense of what's been changing and follow that. But it's, I would say, even less accessible than a wiki. It's very challenging to search, but maybe a little bit more accurate because it's a little bit more timely. GitHub, GitHub's up there because the search is a little bit better than Wikis. And it has the same accuracy as a little bit more accurate than JIRA because it's still timely. I can look at the issues. I can look at pull requests. If you really want to nail accessibility, comments, comments have a bad rap, understandably. And that's why I've put it pretty low on accuracy. It's super accessible, which is probably the reason we often turn to comments as a way of documenting things because it's right there in the code. It checks that box of, I don't even have to leave the text editor. However, as we've probably, as a lot of us may have experienced, they're not always accurate. It's easy to change the method, change what's happening, and forget to update the documentation. And so we're here to talk about Git. Git is what I think the best of both of these. I'm going to show in a few minutes some different ways that it's hyper accessible through text editor integrations. And it's very accurate. As you are modifying the code, you're going to write a new message that describes the change. And because that change, that message is attached to the code that is changing, if you overwrite a method, you're now going to have the new message. You are automatically updating the documentation associated with that. Here's an example. So code I was looking at in this application. And something about this caught my eye. It's that comment. So if we go, if we have 99999, and we want to generate the next one, this is for generating purchase order numbers. We wrap back to one. And my first instinct is, are we going to start overwriting PO numbers? What's going to happen? Why, you know, what is going on here? Why, why is this the behavior that you want? I can look at the code itself and see the how, but I couldn't see the why. And so I followed my instincts. I looked at the Git blame. And this is the message I saw. Work in progress, generate PO numbers based off of starting point. Now to be fair, this commit was written four years ago. So it's a different time for the company. We're moving fast. And so, but it's not unsurprising to see these kinds of commits in our repositories. More recently, I did this. This is some work that I'm doing. I'm actually still working on this. There's one of our pages where we wanted to change the CSS to a new framework. And it's not, you know, really prioritized in our sprints. It's something that I tend to just hack on every, you know, whenever I have 30 minutes, whenever I can just take a few minutes to update a new little part. And so it's resulted in a lot of work in progress commits. The changes aren't often atomic. And so I don't, you know, have time or much, there's not anything to unite the commit that I would give it a good message. And so it just has developed into this work in progress mess. And I want my commits to be valuable to my coworkers. I want them to provide context. And what I just showed you clearly isn't going to do that. If somebody get blames, they're not going to understand any of the issues that I ran into updating the CSS or why I may have changed the button color. I have sacrificed that documentation with this bad history. So let's talk real quick about how we can use the history. The simplest is to get log. If you just run it in your terminal, you're going to get a very verbose output. And so it's maybe not the most useful on its own, but if you pair this with some of the command line options, you can search through your get history. And if you're using a GUI, which is prep-ad-d-d-j, then you can also search through GUIs. So there's a lot of richness just in the get-log command. My favorite way, and the way I more often use it, is with get-blame. So here's an example of a get-blame integration with BS code. You can probably barely see it, but off to the right of each line that I've highlighted, there's a little annotation that shows the commit author. And I think it's also the how long ago, how long ago that was changed. And if you hover over it, you get this nice little pop-up, gives you a little bit more information, includes a link that takes you right to GitHub if you want to view it there, if you want to share it with someone. Pretty great integration with BS code. And then here's another example. This is Adams. Adams I like because it has this heat, this little heat map bar. And so the more orange that line is, the more recent it is, and blue is older. That's nice if you're just getting into a file and you want to see what's been happening in this code recently, or if you're debugging and you want to see maybe somebody made a change that had some unexpected consequences. This is a really cool integration. But all of this depends on writing good commit messages. So if we are, you know, we can see how, it's not helpful enough to just know that it commits recent or old, but we also need to include all this information. So let's take a few minutes to think about what makes these commit messages valuable. The first thing is starting off with a good title. So I like this convention. This is I think pretty liberally borrowed from Tim Pope's blog post. I like this convention of starting with a capitalized verb. We'll go through some examples, but for example, one example is add a blog post, or add posts, or update CSS. And follow that with a description. This is where I think a lot of times we move a little too fast. This is a wonderful place to take a second and just think about yourself in a week or a month or a year. What questions are you going to ask? If you were to look at this code again, what is going to make you raise an eyebrow? What do you think somebody else is going to wonder? What do you want to make sure people aren't tapping you on the shoulder or writing you in Slack? You want to try to answer these questions for them if you can. And it's not just, you know, I personally, I don't know if this is selfish or lazy or what, but I really like to think about myself about this. For some reason it just really helps motivate putting the right content in here. And so, yeah, it's good to focus on your descriptions. And then last is an issue tracker. For the most part, you will be using an issue tracker. Maybe it's GitHub issues, maybe it's JIRA, the little tracker. If you include a reference to your issue tracker in the commit message, this gives people a way to find their original issue and again, just kind of connect it to the business context, connect it to the bigger picture. So here's an example of a commit I was working on. So I'm just going to, for this, all these examples, we're going to say I'm working on a blog. So this is my commit message. Let's try to apply those guidelines we just talked about. So if I start off with ad posts, the first thing we can see is that we need to work on that title. So let's capitalize the first letter. And you know, this seems like a really minor, like, pedantic thing, but it adds a lot of visual cohesion or professionalism. It adds that nice touch to your Git history and it's almost evocative of a broken Windows principle that if you just show that you take that level of care, that somehow motivates others and says, like, we care about this. So here's just a slightly more descriptive title. I'm not doing too much in this commit. I'm just generating a post model and a table. But there are some details I can add. So I can write a small sentence about it. Maybe I'm not adding too much detail, but I am highlighting that the posts have a title and body. I'm also calling out that maybe somebody looking at this in the future would wonder why I didn't associate posts with a user. Surely that's something you'd have to have. Well, I can highlight that that's coming in a future story. And so don't worry. And then, of course, we have to add our issue tracker. So we still have this mess, though. I've written all these bad commits. What am I going to do about this? Let's talk about some tools that we can use to help work with our Git history. First, it's rebasing. This one has developed quite a reputation. And I feel like I've run into a lot of junior engineers who were told at one point to just never rebase. Just don't worry about it. It's going to ruin the history. And you're going to destroy my work. So just don't ever do it. And that's what I was told when I started out. But then I started talking to other engineers, reading some blog posts. And there's a tutorial I'll share in a minute that was also really helpful. And once I got my head around what's happening, it really empowered my Git workflow. And so I'm going to go through a really... This is the simplest rebasing example I could think of. But I hope it helps give you some visual model of what's happening. So in this example, we are on the master branch. I'm only showing two commits. And head is a reference. It's just saying which branch am I currently on? So if I were to run Git status right now, you can see confirmation I'm on master. So as we're going along, you'll see that head reference move around. All right. So let's start our new feature. This is going to be a feature I'm adding in post model. So I'm going to check out with the dash B flag to create a new branch. And you can see it's out of the new branch. And that head reference has now moved up because I'm now on add post. I've done some work. We're going to give it a not so great commit message, but we're going to just for this example make a quick commit. And I'm going to switch back to master. This is... Let's say I'm working on this with my buddy and I know that they just made some... They just merged the pull request into master. And I want to make sure that I'm working on the most recent version of master. So I need to switch back to master and then I run get pull. I'm just going to get that new work and fast... It's going to move master along. So you see there's now this divergence in the history. And this is where rebasing becomes valuable. I can switch back to add post and I can run get rebase master. When I do this, get is going to take the commit, this commit, in this case we only have one commit, it's going to take this commit and it's going to change the base of it from that original commit 3, 2, 0 and it's going to change the base to master. So it's going to replay that work on to master. And when it does that, it's going to generate a new shawl. This is something just to keep in mind. We're going to come back to the consequences of this. This is where it can kind of create headaches for people. That's the simplest example of rebasing I can think of. So let's make it a little bit more complicated. In this example, I've done three commits worth of work and let's say we still have some work in progress in there and I don't really want that to live forever. So let's this time do an interactive rebase. This is by and far the most powerful way to do a rebase. Although it's going to pop up this giant wall of text. But don't be worrying, most of this is just documentation. So everything on the bottom that starts with a hash is just documenting what you can do with an interactive rebase. And everything at the top are your commits. So these are those three commits that are within this rebase and it's going to apply them from top to bottom and what it's going to do is on the far left where it says pick, that's the instruction. So it's telling get, you should just pick this commit. If we were to close the editor right now, it would work as if we hadn't done an interactive rebase anyways. But there are a lot of other options we can use and these are the ones that I end up using the most. I know this text is small so I hope people in the back can still read it. So pick is the one that we were already on, it's the default. That's just going to use the commit, use the message and everything just moves on. Reword is going to use the commit and give you a chance to change the message. So if you, this one I end up using a lot because I will often get carried away working and forget to add the issue tracker to my store, to my commit messages. And so I'll do an interactive rebase and I'll reword the commits which gives me a chance to add that issue tracker back in. Squash is going to take the commit and combine it with the previous one and fix up is just like that but it's going to discard the message. So with squash you're going to have a chance to edit the message, fix up, it's just going to get rid of the message. So in this example, let's say we want to pick that first, we want to pick that first commit and then the next two commits, we want to combine into the first commit. So we're going to change the next two lines to squash. When we close the editor, it gets going to again pick up those commits and it's going to open up another editor. So this is because we did squash, it's going to give you a chance to update the commit message. So this is the original commit message but we just did some work on creating a new commit message. So let's get rid of that and then let's add in our new commit message that's descriptive, that's a good title and has a link to our issue tracker. Now when we close the editor, it's going to do its thing, it's going to combine these commits and it's going to replay it on the master and once again give it a new shawl. So these are two very, you know, these are probably some of the simpler cases of rebasing. If I wish I could spend more time going through examples, I love rebasing. This is a great resource, learn and get branching. If you aren't familiar with it, I highly recommend you check it out. It goes, it starts from a very simple, I think it starts with just like creating a commit and then takes you all the way up to like really intense rebasing and like combining different crazy branches that I hope you never end up in that situation. But it's super good practice. And by the way, I will, I have at the end of this a link to everything that I'm referencing and I'll publish my slides on mine so these will be available. Okay, so we've covered rebasing. So let's talk about amending commits. This happens to me way too often. I think I'm done and then I realize, yeah, I got to run the test suite and I run it and I get a failure. So one option is I can fix it, I can add those changes and create a new commit that's just fixing the test. And I, you know, this is, you see this all the time. I do. This is fine. If we look at the log, the problem is we have this, we have two commits that are now, neither of them are atomic commits. This is a word you may have heard about commits. It's this idea that a commit is an isolated change and it can exist, like, on its own. That right now there's a dependence that we couldn't release this without 89F. But, and so that means that that B9E commit is not atomic. The test suite was not green. So that's one of the downsides of this. Another is that it's not, it doesn't help my coworkers get context on what's, what change is happening. So, if my coworker goes and looks at these tests that I had to fix and they try to understand what was happening and they want to understand why the test was written this way or what feature we were working on, they're going to see fixed tests as their commit message. And that's not what the feature was. That was a consequence of the fact that I broke the test. The feature was I added posts. And so it's not providing enough, it's not providing as much context as it could. But we have an option and this is the amend flag with committing. So with dash dash amend, Git will open up the editor again and give us a chance to change the message. And so this is, this is more powerful than just adding in new work. It's also useful if you realize that you need to make a change to the commit message. But in this example, I'm just focusing on, we've made some fixes and we need to combine them with the previous work. So here I can commend, I can amend it. Looks, you know, the message isn't going to change. So that's fine. And when I exit, it's going to just make another commit. It's going to make this, it's going to update that commit. And of course we can run our tests, see we're all green, it's great. Now we can look at Git log. We have a nice, clean history. It's descriptive and it builds context for our co-workers, explains what we were doing. So let's push it up. Ah, dang it. Ah, rejected. So if you've done any of this before, you've probably ran into this. And this is where that detail about the shaw changing comes in. There's a, and this is also I think why a lot of times junior engineers are told just to avoid rebasing. Because there's a bit of a decision tree that emerges. So this is roughly what happens in my head. There's a lot of nuance to this. And so don't, you know, but yeah. For me, we are using a pull request workflow at Stitch Fix. So each feature starts out as a new branch. And I own that branch. I'm the only one working on that branch. The powerful thing about that is because I'm the only one working on that branch, I'm not at risk of, and I'm not at risk of messing up someone else's work if I were to rebase and push, or force push, which we'll show in a minute. However, if you are not using that type of workflow, or if you are working on a feature branch with someone else, then you should not rebase. You should not amend. There's a lot of danger in how you could potentially lose other people's work. It's not, yeah. So let's now try that push again. This time we're going to use a different range of flag. There's actually two ways to accomplish this. This one is a slightly safer way. So the simplest way is with just dash dash force. When you do that, Git is going to just tell GitHub, take this. I don't care what you have. I don't care if anyone's done anything on it. My version's the right one. Take it. Force with least is a slightly gentler version of that. You're still telling Git, take this. I know that I'm changing the history from what you have, but it's instead saying if someone else has changed the history since I last pushed, then reject me. And so this is a slightly safer way. Just in case one of your co-workers decides to unexpectedly contribute to your feature branch, this is a way to avoid that. Okay. So let's go back to this. There is yet another way that I like to deal with messy Git history. And it's probably the way that I'll end up dealing with this. The reason is because of the nature of this work, I ended up with a lot of merge conflicts. And instead of trying to rebase my branch onto master, I ended up back merging master into my branch, which I didn't talk about, but is another way of keeping my branch up to date. And so the Git history for this is quite a mess. But it doesn't mean that I have to let this make it onto the master branch. I can still, I still have one more chance to clean it up before it makes it to master. And it's this option. If you click this little arrow, when you go to merge or commit, there's this squash and merge option. What it does is it's doing that same, you know, rebase squash that we just went through and it's giving you the chance here to edit the commit message. So here, you can see I've just taken, I already have the description written well and so I just copied and pasted that, updated the commit message and merged it. So now, even though I started off with a mess of work in progress commits, what's made it, what it eventually makes it into master, I will be able to add more context and color to it so that it's helpful for my coworkers. So bringing it back, I just, yeah, I just want to talk about accuracy and accessibility. And I've also added to sickness here because I find that it kind of speaks to how quickly you can find answers in Git if you and your coworkers invest the time and effort into writing quality messages. So thank you again for coming out and hearing my talk. I work at Sitchfix. This is my Twitter handle. You can try to reach out to me. I'm not a huge Twitter person but I will try to pay attention. So email is another option. And again, I'll put my slides up on the speaker deck, I think, is the website. And so all of these links will be accessible. So there's the Tim Pope article about commit messages, force with wheezes and Atlassian article, that's pretty good. And then that learn Git branching is a great tutorial. You can also just Google it and it's pretty easy to find. So thank you. And thank you, see you later.
 Thanks for everyone for joining me in this discussion.  Today I want to talk about Git, commit messages, and some unexpected value that they can provide  as a form of documentation.  Starting out, I want to talk about complexity.  I started a stitch fix a little bit over a year ago, and we have pretty good onboard  documentation.  I read the Wiki, I read your first day, got my computer set up, and I felt like I had  a pretty good sense of the teams and the apps.  Then the rubber met the road and I got my first story.  My team works on an application that's been around for about six years now.  It's accrued a lot of complexity.  So add to this, the first story I took was a bug fix.  So as I got into it, this is just what it felt like.  I felt like I was dealing with a lot of different pieces and they're connected to each other,  but it wasn't exactly clear why or how they're connected or when I'm changing something here,  what's going to happen elsewhere.  And so it got me thinking about documentation and where I could look for the answers to  this question.  And two different metrics stand out for me as a way of thinking about my documentation.  Accuracy and accessibility.  So accessibility to me means that I don't have to work too hard to get it.  If I have to look at documentation often throughout the day, if it takes me a minute  to find an answer, and I'm doing that a couple dozen times, that's 30 minutes.  It really adds up.  And so if I can get an answer quickly in a few seconds, that's perfect.  If I don't have to read my text editor, that's even better.  Accuracy is kind of like what it sounds like.  It's a sense of, is the information I'm reading, is it correct?  Or has something changed?  Has the code evolved in a way that is separate from the documentation and now what I'm reading  about it is incorrect?  So one of the ways we can get answers is with, my phone will connect.  All right, we're going to do it this way.  It's with wikis.  So this is how I started, we're going to get all the transitions now.  Wikis are great for the onboarding stuff, the new hire, the high level.  You're not going to change it very often.  But you see, I put it down here in this bottom left because they're not super accessible.  Yes, you can search some, but for me, in my experience, the search just never seems to  work as like I want.  I always have a hard time.  And they're not always accurate.  So for new hire stuff, they're good.  But if you were to try to document that circuit diagram, that entire system in a wiki, it  would just very quickly go out of date.  Next is JIRA.  So issue tracker is maybe use pivotal tracker.  We use JIRA at Stitch Fix.  And I can look at recent issues and try to get a sense of what's been changing and follow  that.  But it's, I would say, even less accessible than a wiki.  It's very challenging to search, but maybe a little bit more accurate because it's a  little bit more timely.  GitHub, GitHub's up there because the search is a little bit better than Wikis.  And it has the same accuracy as a little bit more accurate than JIRA because it's still  timely.  I can look at the issues.  I can look at pull requests.  If you really want to nail accessibility, comments, comments have a bad rap, understandably.  And that's why I've put it pretty low on accuracy.  It's super accessible, which is probably the reason we often turn to comments as a way  of documenting things because it's right there in the code.  It checks that box of, I don't even have to leave the text editor.  However, as we've probably, as a lot of us may have experienced, they're not always  accurate.  It's easy to change the method, change what's happening, and forget to update the documentation.  And so we're here to talk about Git.  Git is what I think the best of both of these.  I'm going to show in a few minutes some different ways that it's hyper accessible through text  editor integrations.  And it's very accurate.  As you are modifying the code, you're going to write a new message that describes the  change.  And because that change, that message is attached to the code that is changing, if you overwrite  a method, you're now going to have the new message.  You are automatically updating the documentation associated with that.  Here's an example.  So code I was looking at in this application.  And something about this caught my eye.  It's that comment.  So if we go, if we have 99999, and we want to generate the next one, this is for generating  purchase order numbers.  We wrap back to one.  And my first instinct is, are we going to start overwriting PO numbers?  What's going to happen?  Why, you know, what is going on here?  Why, why is this the behavior that you want?  I can look at the code itself and see the how, but I couldn't see the why.  And so I followed my instincts.  I looked at the Git blame.  And this is the message I saw.  Work in progress, generate PO numbers based off of starting point.  Now to be fair, this commit was written four years ago.  So it's a different time for the company.  We're moving fast.  And so, but it's not unsurprising to see these kinds of commits in our repositories.  More recently, I did this.  This is some work that I'm doing.  I'm actually still working on this.  There's one of our pages where we wanted to change the CSS to a new framework.  And it's not, you know, really prioritized in our sprints.  It's something that I tend to just hack on every, you know, whenever I have 30 minutes,  whenever I can just take a few minutes to update a new little part.  And so it's resulted in a lot of work in progress commits.  The changes aren't often atomic.  And so I don't, you know, have time or much, there's not anything to unite the commit that  I would give it a good message.  And so it just has developed into this work in progress mess.  And I want my commits to be valuable to my coworkers.  I want them to provide context.  And what I just showed you clearly isn't going to do that.  If somebody get blames, they're not going to understand any of the issues that I ran  into updating the CSS or why I may have changed the button color.  I have sacrificed that documentation with this bad history.  So let's talk real quick about how we can use the history.  The simplest is to get log.  If you just run it in your terminal, you're going to get a very verbose output.  And so it's maybe not the most useful on its own, but if you pair this with some of the  command line options, you can search through your get history.  And if you're using a GUI, which is prep-ad-d-d-j, then you can also search through GUIs.  So there's a lot of richness just in the get-log command.  My favorite way, and the way I more often use it, is with get-blame.  So here's an example of a get-blame integration with BS code.  You can probably barely see it, but off to the right of each line that I've highlighted,  there's a little annotation that shows the commit author.  And I think it's also the how long ago, how long ago that was changed.  And if you hover over it, you get this nice little pop-up, gives you a little bit more  information, includes a link that takes you right to GitHub if you want to view it there,  if you want to share it with someone.  Pretty great integration with BS code.  And then here's another example.  This is Adams.  Adams I like because it has this heat, this little heat map bar.  And so the more orange that line is, the more recent it is, and blue is older.  That's nice if you're just getting into a file and you want to see what's been happening  in this code recently, or if you're debugging and you want to see maybe somebody made a  change that had some unexpected consequences.  This is a really cool integration.  But all of this depends on writing good commit messages.  So if we are, you know, we can see how, it's not helpful enough to just know that it commits  recent or old, but we also need to include all this information.  So let's take a few minutes to think about what makes these commit messages valuable.  The first thing is starting off with a good title.  So I like this convention.  This is I think pretty liberally borrowed from Tim Pope's blog post.  I like this convention of starting with a capitalized verb.  We'll go through some examples, but for example, one example is add a blog post, or add posts,  or update CSS.  And follow that with a description.  This is where I think a lot of times we move a little too fast.  This is a wonderful place to take a second and just think about yourself in a week or  a month or a year.  What questions are you going to ask?  If you were to look at this code again, what is going to make you raise an eyebrow?  What do you think somebody else is going to wonder?  What do you want to make sure people aren't tapping you on the shoulder or writing you  in Slack?  You want to try to answer these questions for them if you can.  And it's not just, you know, I personally, I don't know if this is selfish or lazy or  what, but I really like to think about myself about this.  For some reason it just really helps motivate putting the right content in here.  And so, yeah, it's good to focus on your descriptions.  And then last is an issue tracker.  For the most part, you will be using an issue tracker.  Maybe it's GitHub issues, maybe it's JIRA, the little tracker.  If you include a reference to your issue tracker in the commit message, this gives people a  way to find their original issue and again, just kind of connect it to the business context,  connect it to the bigger picture.  So here's an example of a commit I was working on.  So I'm just going to, for this, all these examples, we're going to say I'm working on  a blog.  So this is my commit message.  Let's try to apply those guidelines we just talked about.  So if I start off with ad posts, the first thing we can see is that we need to work on  that title.  So let's capitalize the first letter.  And you know, this seems like a really minor, like, pedantic thing, but it adds a lot of  visual cohesion or professionalism.  It adds that nice touch to your Git history and it's almost evocative of a broken Windows  principle that if you just show that you take that level of care, that somehow motivates  others and says, like, we care about this.  So here's just a slightly more descriptive title.  I'm not doing too much in this commit.  I'm just generating a post model and a table.  But there are some details I can add.  So I can write a small sentence about it.  Maybe I'm not adding too much detail, but I am highlighting that the posts have a title  and body.  I'm also calling out that maybe somebody looking at this in the future would wonder  why I didn't associate posts with a user.  Surely that's something you'd have to have.  Well, I can highlight that that's coming in a future story.  And so don't worry.  And then, of course, we have to add our issue tracker.  So we still have this mess, though.  I've written all these bad commits.  What am I going to do about this?  Let's talk about some tools that we can use to help work with our Git history.  First, it's rebasing.  This one has developed quite a reputation.  And I feel like I've run into a lot of junior engineers who were told at one point to just  never rebase.  Just don't worry about it.  It's going to ruin the history.  And you're going to destroy my work.  So just don't ever do it.  And that's what I was told when I started out.  But then I started talking to other engineers, reading some blog posts.  And there's a tutorial I'll share in a minute that was also really helpful.  And once I got my head around what's happening, it really empowered my Git workflow.  And so I'm going to go through a really...  This is the simplest rebasing example I could think of.  But I hope it helps give you some visual model of what's happening.  So in this example, we are on the master branch.  I'm only showing two commits.  And head is a reference.  It's just saying which branch am I currently on?  So if I were to run Git status right now, you can see confirmation I'm on master.  So as we're going along, you'll see that head reference move around.  All right.  So let's start our new feature.  This is going to be a feature I'm adding in post model.  So I'm going to check out with the dash B flag to create a new branch.  And you can see it's out of the new branch.  And that head reference has now moved up because I'm now on add post.  I've done some work.  We're going to give it a not so great commit message, but we're going to just for this  example make a quick commit.  And I'm going to switch back to master.  This is...  Let's say I'm working on this with my buddy and I know that they just made some...  They just merged the pull request into master.  And I want to make sure that I'm working on the most recent version of master.  So I need to switch back to master and then I run get pull.  I'm just going to get that new work and fast...  It's going to move master along.  So you see there's now this divergence in the history.  And this is where rebasing becomes valuable.  I can switch back to add post and I can run get rebase master.  When I do this, get is going to take the commit, this commit, in this case we only have one  commit, it's going to take this commit and it's going to change the base of it from that  original commit 3, 2, 0 and it's going to change the base to master.  So it's going to replay that work on to master.  And when it does that, it's going to generate a new shawl.  This is something just to keep in mind.  We're going to come back to the consequences of this.  This is where it can kind of create headaches for people.  That's the simplest example of rebasing I can think of.  So let's make it a little bit more complicated.  In this example, I've done three commits worth of work and let's say we still have some work  in progress in there and I don't really want that to live forever.  So let's this time do an interactive rebase.  This is by and far the most powerful way to do a rebase.  Although it's going to pop up this giant wall of text.  But don't be worrying, most of this is just documentation.  So everything on the bottom that starts with a hash is just documenting what you can do  with an interactive rebase.  And everything at the top are your commits.  So these are those three commits that are within this rebase and it's going to apply  them from top to bottom and what it's going to do is on the far left where it says pick,  that's the instruction.  So it's telling get, you should just pick this commit.  If we were to close the editor right now, it would work as if we hadn't done an interactive  rebase anyways.  But there are a lot of other options we can use and these are the ones that I end up using  the most.  I know this text is small so I hope people in the back can still read it.  So pick is the one that we were already on, it's the default.  That's just going to use the commit, use the message and everything just moves on.  Reword is going to use the commit and give you a chance to change the message.  So if you, this one I end up using a lot because I will often get carried away working and  forget to add the issue tracker to my store, to my commit messages.  And so I'll do an interactive rebase and I'll reword the commits which gives me a chance  to add that issue tracker back in.  Squash is going to take the commit and combine it with the previous one and fix up is just  like that but it's going to discard the message.  So with squash you're going to have a chance to edit the message, fix up, it's just going  to get rid of the message.  So in this example, let's say we want to pick that first, we want to pick that first commit  and then the next two commits, we want to combine into the first commit.  So we're going to change the next two lines to squash.  When we close the editor, it gets going to again pick up those commits and it's going  to open up another editor.  So this is because we did squash, it's going to give you a chance to update the commit  message.  So this is the original commit message but we just did some work on creating a new commit  message.  So let's get rid of that and then let's add in our new commit message that's descriptive,  that's a good title and has a link to our issue tracker.  Now when we close the editor, it's going to do its thing, it's going to combine these  commits and it's going to replay it on the master and once again give it a new shawl.  So these are two very, you know, these are probably some of the simpler cases of rebasing.  If I wish I could spend more time going through examples, I love rebasing.  This is a great resource, learn and get branching.  If you aren't familiar with it, I highly recommend you check it out.  It goes, it starts from a very simple, I think it starts with just like creating a commit  and then takes you all the way up to like really intense rebasing and like combining  different crazy branches that I hope you never end up in that situation.  But it's super good practice.  And by the way, I will, I have at the end of this a link to everything that I'm referencing  and I'll publish my slides on mine so these will be available.  Okay, so we've covered rebasing.  So let's talk about amending commits.  This happens to me way too often.  I think I'm done and then I realize, yeah, I got to run the test suite and I run it and  I get a failure.  So one option is I can fix it, I can add those changes and create a new commit that's just  fixing the test.  And I, you know, this is, you see this all the time.  I do.  This is fine.  If we look at the log, the problem is we have this, we have two commits that are now, neither  of them are atomic commits.  This is a word you may have heard about commits.  It's this idea that a commit is an isolated change and it can exist, like, on its own.  That right now there's a dependence that we couldn't release this without 89F.  But, and so that means that that B9E commit is not atomic.  The test suite was not green.  So that's one of the downsides of this.  Another is that it's not, it doesn't help my coworkers get context on what's, what  change is happening.  So, if my coworker goes and looks at these tests that I had to fix and they try to understand  what was happening and they want to understand why the test was written this way or what  feature we were working on, they're going to see fixed tests as their commit message.  And that's not what the feature was.  That was a consequence of the fact that I broke the test.  The feature was I added posts.  And so it's not providing enough, it's not providing as much context as it could.  But we have an option and this is the amend flag with committing.  So with dash dash amend, Git will open up the editor again and give us a chance to change  the message.  And so this is, this is more powerful than just adding in new work.  It's also useful if you realize that you need to make a change to the commit message.  But in this example, I'm just focusing on, we've made some fixes and we need to combine  them with the previous work.  So here I can commend, I can amend it.  Looks, you know, the message isn't going to change.  So that's fine.  And when I exit, it's going to just make another commit.  It's going to make this, it's going to update that commit.  And of course we can run our tests, see we're all green, it's great.  Now we can look at Git log.  We have a nice, clean history.  It's descriptive and it builds context for our co-workers, explains what we were doing.  So let's push it up.  Ah, dang it.  Ah, rejected.  So if you've done any of this before, you've probably ran into this.  And this is where that detail about the shaw changing comes in.  There's a, and this is also I think why a lot of times junior engineers are told just  to avoid rebasing.  Because there's a bit of a decision tree that emerges.  So this is roughly what happens in my head.  There's a lot of nuance to this.  And so don't, you know, but yeah.  For me, we are using a pull request workflow at Stitch Fix.  So each feature starts out as a new branch.  And I own that branch.  I'm the only one working on that branch.  The powerful thing about that is because I'm the only one working on that branch, I'm not  at risk of, and I'm not at risk of messing up someone else's work if I were to rebase  and push, or force push, which we'll show in a minute.  However, if you are not using that type of workflow, or if you are working on a feature  branch with someone else, then you should not rebase.  You should not amend.  There's a lot of danger in how you could potentially lose other people's work.  It's not, yeah.  So let's now try that push again.  This time we're going to use a different range of flag.  There's actually two ways to accomplish this.  This one is a slightly safer way.  So the simplest way is with just dash dash force.  When you do that, Git is going to just tell GitHub, take this.  I don't care what you have.  I don't care if anyone's done anything on it.  My version's the right one.  Take it.  Force with least is a slightly gentler version of that.  You're still telling Git, take this.  I know that I'm changing the history from what you have, but it's instead saying if someone  else has changed the history since I last pushed, then reject me.  And so this is a slightly safer way.  Just in case one of your co-workers decides to unexpectedly contribute to your feature  branch, this is a way to avoid that.  Okay.  So let's go back to this.  There is yet another way that I like to deal with messy Git history.  And it's probably the way that I'll end up dealing with this.  The reason is because of the nature of this work, I ended up with a lot of merge conflicts.  And instead of trying to rebase my branch onto master, I ended up back merging master  into my branch, which I didn't talk about, but is another way of keeping my branch up  to date.  And so the Git history for this is quite a mess.  But it doesn't mean that I have to let this make it onto the master branch.  I can still, I still have one more chance to clean it up before it makes it to master.  And it's this option.  If you click this little arrow, when you go to merge or commit, there's this squash and  merge option.  What it does is it's doing that same, you know, rebase squash that we just went through  and it's giving you the chance here to edit the commit message.  So here, you can see I've just taken, I already have the description written well and so I  just copied and pasted that, updated the commit message and merged it.  So now, even though I started off with a mess of work in progress commits, what's made  it, what it eventually makes it into master, I will be able to add more context and color  to it so that it's helpful for my coworkers.  So bringing it back, I just, yeah, I just want to talk about accuracy and accessibility.  And I've also added to sickness here because I find that it kind of speaks to how quickly  you can find answers in Git if you and your coworkers invest the time and effort into writing  quality messages.  So thank you again for coming out and hearing my talk.  I work at Sitchfix.  This is my Twitter handle.  You can try to reach out to me.  I'm not a huge Twitter person but I will try to pay attention.  So email is another option.  And again, I'll put my slides up on the speaker deck, I think, is the website.  And so all of these links will be accessible.  So there's the Tim Pope article about commit messages, force with wheezes and Atlassian  article, that's pretty good.  And then that learn Git branching is a great tutorial.  You can also just Google it and it's pretty easy to find.  So thank you.  And thank you, see you later.
RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_0_59.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_60_155.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_156_275.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_276_407.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_408_779.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_780_2351.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_2352_7067.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_7068_7907.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_7908_9659.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_9660_10823.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_10824_11435.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_11436_12359.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_12360_13715.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_13716_14123.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_14124_17363.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_17364_19835.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_19836_20195.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_20196_25223.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_25224_28115.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_28116_28235.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_28236_28823.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_28824_29315.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_29316_30275.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_30276_33239.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_33240_33911.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_33912_34547.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_34548_35255.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_35256_36959.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_36960_38327.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_38328_39515.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_39516_39563.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_39564_39923.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_39924_40127.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_40128_40823.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_40824_41543.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_41544_41903.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_41904_42551.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_42552_42719.png RubyConf_2018_-_Documentation_Tradeoffs_and_Why_Go_cdpaQ6R7100_42720_42868.png