 Name of the talk, commit messages to the rescue. My name is Ajie, so it's a pretty short name, but a lot of people still have trouble with it. Spelled right up there, AJI, and you say it like, ah, gee, just like that. And just so that you never forget who I am, I'd like you all to do it along with me, okay? I'll spell it out, AJI, and I wanna hear you say Ajie, okay, AJI, ah, gee. That was good, that was good. But you didn't do the snap. So one more time, if you would humor me, please. AJI, ah, gee, excellent, I like it. The entire room sounds disappointed in me. Good thing I'm comfortable now, though. So my pronouns are he, him. Website is in the upper left, Twitter is in the upper right. If Twitter is a thing that you do, and I 100% understand if you just can't. And I know that you have a choice in conference talks, and I wanna thank you for being here with me. I work for a company called Snapsheet based in Chicago. We're not unleashing the world's creativity or anything. And I don't honestly have a pithy one-liner to explain what we do, but a story from a friend of mine I think is the best way to describe it. He called an Uber, went down, stood outside, waiting for the Uber, stood next to his motorcycle, and the Uber pulled up and smashed right into his bike, knocked it over. The Uber driver said, oh no, it's okay, which is terrifying in and of itself. He said, no, it's not, that's my bike. And he anticipated weeks of shopping around at body shops and having to fight with his insurance carrier and seeing which one he could get and if it would ever get fixed in months. But the next day he got a text from his carrier to download our app, took pictures of his damage with the phone and he had money in his account the next day. So technically our customers are the insurance companies, we're streamlining processes, saving millions of dollars, increasing efficiency, but it's what we can do for the people like Brett that make it exciting for me. And here's where I insert the obligatory we're hiring statement, come work with me and let's make beautiful commit messages together. I give a lightning talk version of this before and I wanted to set up some of the situations in which commit messages could really save your bacon. So I fabricated a story about a workplace that could have been helped by good message practice. When looking at what pictures to put on my slides during this story, I reached for Dr. Seuss imagery. I especially liked it because the fish could be the project manager and that just felt right to me. So I started looking at the pictures and thinking well I'm gonna give this talk at RailsConf. That's a little bit bigger than the other venue. Why not go all out? So I present to you, get add, get RM, get commit minus M. Definitely not by Dr. Seuss. An e-commerce site on AWS is a good enough scene for our story, I guess. They employed devs much more than a few but I'd like to speak of thing one and thing two. Now thing one took some work from their burn it down chart seems a bug had been found in the site's shopping cart. Even through all the planning down deep in Rails magic requests had timed out causing dips in their traffic. Thing one raced to make known what was causing the fault. Sweating, anxious the server might catch fire and halt for a week without sleep many cans of liqueur. At long last I've uncovered our one tragic flaw. With git blame we find out that thing two wrote the class that for the last week was a pain in our workflow. Now it's readable, tested, but something's amiss. No one class should employ as much logic as this. It made sense at the time said thing two unrepentant and you know all of my code is self-documenting. So you say said thing one but it needs a refactor. Now help me find out just what that method is after. Seems like dead code to me not much more than obstruction then their fix was merged in and they pushed to production. I had so much fun doing this you guys. But their sigh of relief only lasted a flash never before had a site started crashing so fast. Looking at server logs their heart beats all quickened. Hey I wonder if we could ask that Sean Griffin. He maintained active record his opinion I trust. Nah he'll just tell us we should have used Rust. So call Aaron Patterson call DHH. We're hemorrhaging money all over the place as our devs contemplate the lost data and sales. Think when code loses context apps run off the rails. See what I did there. Okay fun's over down to business. Commit messages we all do that. Thank you. Commit messages we all do them and kind of like TD we all agree that they're very important but we probably cut some corners here and there. And I don't want to stand up here and tell you all that you're doing something wrong because you're not. You might just not be getting the most out of your commit messages. In general version control is something that's taught fairly early on in learning to code. So the concepts need to be imparted in uncomplicated ways and I bet I know a couple of those. It's a save point like in a video game or a moment captured in time or saving your work as you go along. Whether it was like those or not I'm fairly confident that there wasn't too much time spent on it and we all just use dash M. At the time either when you're first learning coding or first learning get there's a lot to take in. It is a little inaccessible at best. So simplifying the steps is important to help learn. So we're shown dash M told to write a brief description and move on. Especially because if we type get commit without the dash M we were going to get stuck in a twilight zone from which there is no escape. Yes that's right. Get commit was going to land us in VIM. And now much like I've seen the one true light and use VIM as my daily driver. Now that I have more familiarity I've circled back around to commit messages and get. Because when these messages aren't thought about as a tool but as a hindrance to work or as a chore that we have to do that doesn't really matter we end up with messages that are unhelpful, incredulous, maybe a bit on the nose. Even desperate, dishonest, depressing, downright belligerent. Yeah I've got nothing. I like though that couple kiss didn't get translated into an emoji. So I listened to a podcast called The Bike Shed and in days gone by it was hosted by Sean Griffin and Derek Pryor and somewhere in there who really remembers when Sean started to talk about what a good commit message was and how it can save you from bad situations. I thought to myself, all right this is a guy who talks about complicated code concepts like it's nothing. And so often I have no idea what he is talking about but commit messages there's a bit of wisdom from this programming celebrity that I can put into practice. So I started to look into commit messages. I read some blogs, a forum poster too, plenty of stack overflow questions and a few pieces of advice rose to the top time and time again. Show of hands, how many people who've heard or seen rules a lot like this? And you use them? Lots of hands went down. How many people are seeing these ideas for the first time? Okay. Some of these have reasons behind them. You keep the subject short because Git, Git Hub will truncate it around 50 characters. Capital letter, period, tense, you use. Those are all just tabs and spaces. There's a convention that we gravitate to, probably those rules but if your team or your project prefers something else, has a different style guide, we'll go for it. And dash M, well we'll see why that shortcut same as an ice cream breakfast. It's nice at the time but it's not gonna help you get through the day. Let's take a moment and look at some well-intentioned commit messages that pull off a GitHub. Again, please with a show of hands, how many of you have written a commit message like this? Or this one? What about this one? So what all of these examples have in common? They all follow those canonical rules, don't they? They might enforce some stylistic consistency but really they're addressing the wrong things because those examples all had something else in common. Every last one of those did not include a body to the commit message. And the habit of not using message bodies is so prevalent that I bet there are some developers out there who are capable, smart, great developers that have never written a commit message body. There might be some at this conference or even in this room. And to you, if you're out there, I cannot wait to share this new perspective on this boring, common tool because it absolutely can be a game changer. Now we've seen some examples and it seems pretty easy to agree on what makes a commit message unhelpful. So what goes into a good commit message? This is from an open source project by Thoughtbot called Clearance. With the subject line, I'll read this out because it might be hard to see, actually that's pretty big, but use route independent password reset redirect. The body is using edit user password URL requires that particular path helper to exist. That's not necessarily the case. Since all we want to do is redirect to the same action we can use URL for instead. It's a concise but descriptive subject. In two sentences, this message conveys the problem that required a change to be made, the intention of the code originally and therefore what the change is aiming for and references the main point of the solution. This is the little commit message that could so much conveyed with only as much text as it needs. Sure, this is more to type than a 50 character dash M message but wouldn't you already have this kind of information in your head if you had just made this change? It's not really a lot of extra work to make this kind of thing happen. Let's take a look at an example from Rails. Fix secret key base for rail ties. This was missed in the security fix for local dev. CI doesn't have attempt directory and the app's built for testing so these end up failing. This adds the secret key base so we don't need to generate one. This talks about the problem being fixed, even where and how the bug was introduced and this can certainly be useful, mentions what this commit adds and why. Again, this is less than the amount of information that you would share with someone who walked by your desk and asked what you were working on but it gives us a lot to work with if we're thinking about under changing the underlying code. So what made those messages better than some of the others that we've looked at? Context. But why is context so important? Well, to illustrate my point, I'm going to go back to a Dr. Seuss story, not another poem, sorry, but a story about Theodore Geisel, that's his real name, and one of his stories, Horton Here's a Who, that Arielle thankfully left out of his slides so that I could still do it. In which an elephant named Horton vows to protect a tiny civilization that's floating on a speck of dust, met with ridicule from the other animals who can't or won't hear them. Horton proclaims, a person's a person, no matter how small. Well, here's some context for you. Theodore Geisel was born in 1904 and like many white people at the time was pretty darned racist. I'm not gonna put those images on screen but famously he do troubling images of Japanese citizens in the run-up to World War II as a political cartoonist amongst far too many other examples. But after the war he traveled to Japan and met the people there, saw the relationship with the American occupation and heard their direct experience with nuclear weapons. He wrote Horton Here's a Who as an allegory about the war. Some lines in there are straight references to the atom bomb falling from the sky. He also drew this cartoon. At the top it says what this country needs is a good mental insecticide, which is a line of Americans coming up to Uncle Sam to have insecticide sprayed in their ear and forcing out the racial prejudice bug. Without the context, Horton is a silly book with a good message. With context, it becomes one man's attempt to admit to the wrongs of his past attitudes in a very public way. He tried to influence others to realize the same mistakes in themselves or at the very least, inoculate the young ins as best as he could. Just as a work of art cannot be fully understood without context, code can be difficult to impossible to wrap your head around without it. The commit itself is going to tell you who, what, where, when, how, but it's missing why. It's a blessing and a curse of programming that there are a million different ways to solve every problem. It's less like engineering and math and more like creative writing. We're constantly making decisions that have consequences to the future. And there's always a reason that we make the decisions that we do, even if it's sometimes a little thin. Record that reason in a commit message because you or someone else might need it. I mean, how many times have you looked into a file that you didn't write only to think, why does this look like this? Wouldn't it be great if we could hover over a line of code in our editors and read a note explaining exactly why a thing looks like the way it does? Well, you can't. Here it is in VS Code. This is an extremely popular extension called Get Lens. This file is in the Rails source code, an active record, you can see the module name on line three. We're gonna jump down a few lines and hover the mouse on line 44. Look at that, it's beautiful. Have you ever had an annotated Shakespeare book before? It really opens up the text in a way that you probably had never experienced it. How about annotated source code? You've already got it. Who's all this context for anyway? Other developers. Developers who are changing this code or using this API or debugging an issue, basically anyone who might write something that executes our code in the future. But what if I'm the only one working on this? Great, other developers can beam you in the future. To properly review code, you're going to need more than just seeing the change, especially if you're using a tool that truncates a diff, the reviewer might not even be seeing all the code that's affected by this change. If you see there on the left, the line numbers go from 120 to 167. That's 47 lines of hidden code. Who knows what could be in there without opening each and every fold in the UI? Okay, but that's what the PR comment is for. 100% agree. That means also that you're already thinking that context is important. So why wouldn't you save it in the history instead of throwing it out with the code when it gets merged or when the code gets merged? Not with the code, that'd be bad. Has anyone ever searched for something because you're stuck only to find a blog post from one of your colleagues or even yourself that gives you the answer? Anybody? That definitely happened to me. You can have that without Googling or if your internet is down with rich messaging. What's going to be easier to capture? Context while you're closer to your thoughts or a summary at the end of feature work after the fact. It's the same thing with TDD, writing tests up front and as you work or going back in and struggling to cover all your bases. Okay, I'm willing to admit that this is what won me over to actually doing TDD instead of just thinking it was a good idea. When you're in the middle of feature development you have all the energy of an exciting new task. And if we write our thoughts in the get history as we go, we can leverage that immediacy and capture helpful information for the project's future developers. And tooling makes it easy to copy out any relevant information for code review and put it right there in the PR. You don't have to write it twice. The body of a commit message doesn't need to be a novel or an entire page of documentation. The explanation should match the size of the context that you have to share. So what do we write? Well, if it's part of a public interface, how could it be used or extended? What's relying on it? If we're Rails developers, we love conventions. We can all speak more or less the same language and it should be easy for new developers to come onto a project if it all looks railsy enough. Did something need to go against a convention for some reason? Is there a non-obvious side effect that falls out of this change? And really, what does obvious even mean? I know, okay, this never happens, but if it did and the actual execution of a library didn't line up with the documentation, I'll put that thing there too. Are there any gotchas that this code introduces? Are there any pitfalls that you saw when you were up to your elbows in this subsystem that would be good to know about in the future? Think about what precise domain knowledge you have right then that you might wanna remember. And try to write a message that will make sense without seeing the code. It can be kinda difficult, but don't need to replicate the code method for method or anything, but if reading the Git logs without the code open makes sense, then that history becomes a much more useful document. Is there an external resource that applies? Link to a ticket or a feature spec or user story, PR comments, Slack discussions can be deep linked. Resources that you use, that's Stack Overflow, Answers, blog posts, videos, documentation, specification, conference talks from cool guys with bow ties. Remember that links aren't forever. The message should still make sense. We all refer to old code as a reference from time to time. How did I solve this the last time? A little explanation and you're leaving breadcrumbs about how a design pattern, a library or technique worked or didn't work and you're able to be one step ahead next time. I've had a little success with tagging my messages, not Git's tags, plain text tags to search either with GitHub search box or with Git log on the command line, a little example here. I use this convention when it's some piece of work I might want to refer back to and I try to give it a good name, but only two hard problems. So this is in a repo of code for a workshop I led and I think what I need is near the beginning so I'm gonna log in reverse. Didn't see it there though. So we'll try to grep through it. Because this command is a regex after the equal sign we're gonna have to escape the dollar sign and here's the syntax for that command by the way it's git log dash dash grep equals what are you looking for? And there it is. Okay, self-documenting completely self-contained context free code is an unrealistic myth and at worst it's an excuse not to try. Even if you're using a tool like Yard or JS doc which I really like to generate API documentation that's just adding more what. And why we wrote some code one way isn't necessarily going to be helpful for someone looking up what arguments a function takes so why doesn't it really seem to go there? But it can be helpful for someone who's making a change to this code. API docs and code comments, they don't stay in sync with the code as written but commit messages persist exactly the same length of time as the code they describe because new code necessarily changes those commit messages. Change your code, update your docs for free. So we've talked about why we wanna write better messages and how we can assemble a useful git history and it sounds like we're going to get to know our way around some parts of git that might be unfamiliar because treating the commit history as a kind of documentation requires a little more thought towards what commits that you leave behind. Git has a lot of baked in tools to help us accomplish just that, like a message template. Many of us are probably familiar with this message, it's what appears when you start a new commit from the command line but this is customizable. It doesn't have to be the same as this. If a team has a standard of what should be included in a message we can leave prompts for ourselves to fill in. Remember the default message, any line with the octo-thorpe will be ignored. On line 12 we see closes too with an issue number. Git Hub will close the related issue once this commit is merged to the default branch. Little bonus. Any of these keywords actually work on Git Hub, close, closes, closed and if you don't use Git Hub many other tools have very similar features as well. This example has width guides in case we can't set a hard wrap and also includes a reference to tags in the subject line. This is a convention popular in a lot of open-source projects, Angular, Electron, other places. It's called conventional commits and I'm not really gonna touch on that here but the super simplified version is to make commit messages both more human readable and helpful but also machine parsable. Saw that, thank you. Okay, you tell Git where to find the template in the Git config, that's a file that lives in the home directory. Or if you're on Windows, looks something like that. There are plenty of configuration options that are possible in here but the one that we're gonna care about right now is this. Commit in the brackets is the section heading, template equals and then the path to the file that you just made. If this is the only configuration in the file that's totally valid. That is commit templates. You can store those, maybe you have a .files management system, something like that and if you wanna geek out about that in the hall afterwards, I'll be there, you know who you are. Sometimes small changes need to happen after a commit. Whitespace fix or we want to change a variable name but we've written a really great commit message. Insightful, future aware, comment. What's that gonna do for the messages for that file? Well, this is kind of a contrived example, okay, but here's a bit of code. We see that there are some typos. Autocomplete makes that easy sometimes, right? It's valid code still but it's gotta be fixed. If we fix the typo and commit again, what are the commit messages gonna look like if you try to get blame or read through line by line in your editor? Good messages on all the lines but the typo fix overrides it on some fairly important places. Sometimes there are changes that aren't worth the commit message but there still needs to be a commit or maybe there's a commit that you needed for development that doesn't need to be pushed up or merged, right? So you don't have to retype copy paste messages. There's a command to merge commits and we can sweep that typo or whip under the rug. No one even needs to know whatever happened. So if you've had trouble with rebase in the past, that's okay. We don't need to really grok the concept in the same way with this technique. Dash I means this is interactive rebase and we're just gonna change within our current branch so none of that. This allows us a lot of flexibility in manipulating the commit history and it's done by opening a text file in your chosen editor. More on that in a minute. So this is the file that comes up. It's going to serve as a set of instructions to get on how it should handle each commit. We see they're listed out in order. All this to newest. First is the action that we want to get to take for each commit defaulting to pick. Second is the short form of the hash which is an ID for that commit. And finally the subject line of the commit message. Note here that the body of the messages are not displayed, just the subject for now. So another reason why a descriptive subject line is important because try messing around with the get history with a bunch of subject lines like some changes to model. And hopefully the available actions we can use are listed below in the commented out portion. I've kind of lightened some of them out because today we're gonna cover just those four. First up is pick. It's the default action for each commit and it basically means use this commit. Doesn't do anything, replay it into the history just the way it is. Next up is reword. So use the commit but edit the commit message. Let's take a look at what a reword action looks like in practice. So before we start let's take a look at the commit that we want to change. It's the last commit relative to where we are now. So we use get log head tilde to mean show me the message on the commit right before head where I am. We don't need to memorize the content here to understand what happens next. Two paragraphs, you kind of roughly the shape of it. You'll understand. So let's continue on. We'll use our get rebase-i to get started. And first step is to change the text on the line of the commit that we want to reword. Then we're going to save and close the file. Get will read in those instructions and proceed. Get opens a commit prompt, same as if it was a brand new commit but pre-populated to the message that currently exists. We're going to make a really obvious change here to show what's going on. We didn't change the subject line there but we could if we wanted to. And let's log out the same message and see what it looks like now. I'll change. I'll superimpose the old log. I'll change. I'll change because the content of the commit changed with the message but the date, everything else stays the same. Next is squash. I find it most useful for managing unnecessary commits or creating commits that more succinctly encompass the work for a branch because sometimes development needs more commits than we're going to need in master. I'm looking at these three commits. It seems like they're kind of doing very similar things and I want to have the messages and changes merged into one commit to push it up for code review. What I want to do is take the commits on lines three and four and merge them into the commit on line two. So when you label a commit for squashing it will be merged into the commit before it so remember that, squashes move up. And because the contents of the commit has changed, I want to change the subject too. Let's see that a little bit in practice too. We'll fire up our interactive rebase same as before but now we choose squash save and quit save and quit. There it is. The file that is opened is where we tell Git what to do with the messages as three commits become one. Each message is delineated with a comment and each section consists of the commit subject, a blank line and the message. If we did nothing the new commit message would look exactly like this but without the comments. It doesn't seem necessary to me to keep all of the outdated subjects so I'll remove the comments too so I can better see what the finished message is going to look like. And the first line will become our new subject and since this doesn't accurately reflect what this commit is changing we're going to update that too. We'll take a look at the new commit now that we're all done. I'm going to use git log dash dash one line to see a compact version of the log with only the subjects for our git logging. It'll start the printout at the specific commit. There it is. Finally fix up which doesn't really need a whole run through because fix up merges up just like squash but the commit message is just deleted. This is perfect for typos, white space commits things like that. So I could literally spend another hour up here going through git commands and minutia so if you wanted more of that I sincerely hope that you went to Chris Toomey's incredible deep dive into git workshop yesterday and as for me I made a bold promise in the talk description that I would teach you how to do all of this git wrangling in an editor other than Vim I know this is why you're all here that's why I put it at the end. Okay first I do want to show you how to use Vim just enough to not have to open another application. See you can stay in the terminal for all your message crafting needs. Okay git commit will likely drop you into Vim yes and that can be a scary place if you don't know all of the arcane incantations required but you can handle committing and message editing with three commands. Nothing works the way you're used to when you first get into Vim that's because you're in a mode for navigating the text not editing. To edit you must enter insert mode press I to get into insert mode then you can type and move around the way that you're used to even the arrow keys work here when you're done editing you'll need to press escape I don't have a mnemonic for that it's escape you cancel out of insert mode by pressing escape to complete the process you'll type colon wq colon to enter a command w to write and q to quit so all told that's I type your message escape colon write quit now you know Vim but if you feel the need to use another editor Al we're going to have to do is open up that git config and add another setting core as the heading editor equals the command to open your editor from the command line sometimes you're going to have to install that command it should be in your editor's FAQ or the like if you don't already have that set up if you use a GUI editor definitely for atom vs code or sublime you'll need to append dash dash wait to the command or it's only going to open a blank file or you can just run this command from the command line once if you don't want to set up a git config so I am pretty close to out of time but I want to let you know that I'll be tweeting out a copy of these slides as well as a post about all of the other things that I didn't get to cover because after running my talk for the first time I realized it was about two hours long and some things just had to go things like a mini review of my opinions on plugins for most of the major editors and more useful git commands for reading and managing commit history I really like it so I apologize for not being able to get it all together for you to be ready for today but we were woken up this morning by a call from our doggy day care that they had to rush my little boy here to the vet he's fine but it's obviously left me with less time than I thought I had so not religious or anything but hugs at a distance for Henson please so I hope that you have all formed or started to form your own idea of what a good commit message is I think you'll find that the answer to how do we write good commit messages is different for every team every person every situation while still doing its usefulness I'm going to close with my answer to that a line that is very quickly becoming my personal catchphrase probably get it tattooed written on my gravestone maybe next RailsConf will hire a skywriter the answer like the answer to most things is with empathy empathy for your teammates empathy for yourself empathy for developers of the future you might never meet someone earlier in the week said something that I absolutely love when I told them about my talk they called me a commit message archeologist yeah so I encourage you to be commit message archeologists not the same time to leave something behind that can be useful for fellow archeologists and even if you can't convince everyone else that you work with that commit messages should be more than uh-huh if you're one in a team of five and taking up the mantle of meaningful commit messages still means that you'll have 20% more of a chance that a commit message can save your bacon too and once your message saves someone else I'm willing to bet it'll be a 40% chance soon after so I'll leave you with that thought and a paraphrased quote thank you