{"id":2245,"date":"2011-11-21T07:58:11","date_gmt":"2011-11-21T15:58:11","guid":{"rendered":"http:\/\/blog.mozilla.org\/webdev\/?p=2245"},"modified":"2012-06-18T08:46:13","modified_gmt":"2012-06-18T16:46:13","slug":"git-using-topic-branches-and-interactive-rebasing-effectively","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/","title":{"rendered":"Git: Using topic branches and interactive rebasing effectively"},"content":{"rendered":"<p>When I first joined the webdev group at Mozilla I was a <a href=\"http:\/\/mercurial.selenic.com\/\">Mercurial<\/a> refugee who had never used <a href=\"http:\/\/git-scm.com\/\">git<\/a> or <a href=\"https:\/\/github.com\/\">github<\/a>. I was always daunted by git and suddenly I had to learn it really fast!\u00a0 Fast forward to today and I can&#8217;t imagine working on a highly collaborative project without git or github.\u00a0 Here is the workflow we use for the <a href=\"https:\/\/github.com\/mozilla\/zamboni\/\">addons.mozilla.org<\/a> project.\u00a0 I highly recommend it and I&#8217;ll summarize exactly why at the end.\u00a0 It&#8217;s pretty similar to how I&#8217;ve heard a lot of teams work but has some subtle differences.<\/p>\n<h3>Using topic branches<\/h3>\n<p>The first thing I do is sync up with master and create a topic branch for my new feature or bug fix:<\/p>\n<pre>git checkout master\r\ngit pull\r\ngit checkout -b add-email-to-install<\/pre>\n<p>Now I have a branch I can commit code into without affecting master.\u00a0 Git checkout makes it super easy to switch between branches in the same repository clone if I&#8217;m multi-tasking or applying hot fixes.\u00a0 In addition to git checkout, you can also use <a href=\"http:\/\/book.git-scm.com\/4_stashing.html\">git stash<\/a> to switch tasks.<\/p>\n<h3>Commit messages<\/h3>\n<p>It&#8217;s really important to write <a href=\"http:\/\/tbaggery.com\/2008\/04\/19\/a-note-about-git-commit-messages.html\">a well-formed git commit message<\/a>. We always include a ticket number into <a href=\"https:\/\/bugzilla.mozilla.org\/\">bugzilla<\/a>, our tracker, so that anyone can get the full back story about a change.<\/p>\n<h3>Ask for a code review<\/h3>\n<p>Once I&#8217;ve added my feature with passing tests I commit my changes, push to my personal fork of the repository, and ask someone on my team to review the code.\u00a0 On <a href=\"https:\/\/github.com\/mozilla\/zamboni\">addons.mozilla.org<\/a> we just ping each other in IRC with a link to the commit or a link to the <a href=\"https:\/\/github.com\/blog\/612-introducing-github-compare-view\">compare view<\/a>.\u00a0 If no one is around we <a href=\"http:\/\/help.github.com\/send-pull-requests\/\">submit a pull request<\/a>.<\/p>\n<p>Github has a sweet interface where you can write comments directly on the diff, like this:<\/p>\n<p><a href=\"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2251\" title=\"github code review example\" src=\"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png\" alt=\"\" width=\"557\" height=\"412\" srcset=\"https:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png 557w, https:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2-300x221.png 300w\" sizes=\"(max-width: 557px) 100vw, 557px\" \/><\/a><\/p>\n<p>Whoops, another change is needed based on feedback from the code review.<\/p>\n<h3>Fixing up the topic branch<\/h3>\n<p>The nice thing about working in a topic branch is it&#8217;s isolated from master and no one else is tracking that branch so I can use git rebase to create the best commit before merging into master.\u00a0 Let&#8217;s say I have some commits on my branch like this:<\/p>\n<pre>$ git log --pretty=oneline -2\r\n825d662cc69774e412119e1eb7ae0900c29d89a0 Fix: put code in a transaction\r\n31378788f321b46f5e27f9fb51bdd19365636871 Adds email to the install record (bug #NNNNNN)<\/pre>\n<p>What I really want is to combine those two commits into one.\u00a0 I can do that with <a href=\"http:\/\/book.git-scm.com\/4_interactive_rebasing.html\">git rebase &#8212;interactive<\/a>. I type:<\/p>\n<pre>git rebase -i HEAD~2<\/pre>\n<p>Then I&#8217;ll get a prompt for rebasing my last two changes:<\/p>\n<pre>pick 3137878 Adds email to the install record (bug #NNNNNN)\r\npick 825d662 Fix: put code in a transaction\r\n\r\n# Rebase 194b59d..825d662 onto 194b59d\r\n#\r\n# Commands:\r\n#\u00a0 p, pick = use commit\r\n#\u00a0 r, reword = use commit, but edit the commit message\r\n#\u00a0 e, edit = use commit, but stop for amending\r\n#\u00a0 s, squash = use commit, but meld into previous commit\r\n#\u00a0 f, fixup = like \"squash\", but discard this commit's log message\r\n#\u00a0 x, exec = run command (the rest of the line) using shell\r\n#\r\n# If you remove a line here THAT COMMIT WILL BE LOST.\r\n# However, if you remove everything, the rebase will be aborted.\r\n#<\/pre>\n<p>If I put the word fixup next to my second commit, it folds it into the first:<\/p>\n<pre>pick 3137878 Adds email to the install record (bug #NNNNNN)\r\nfixup 825d662 Fix: put code in a transaction<\/pre>\n<p>Now I have one commit (it&#8217;s actually a new commit) that contains all of my changes:<\/p>\n<pre>$ git log --pretty=oneline -1\r\nc7846808c8296dd49d49612101aaed7cdfd6d220 Adds email to the install record (bug #NNNNNN)<\/pre>\n<p>Pretty slick, right?<\/p>\n<p>Typically you&#8217;d want to wait until everyone has had a chance to review your code before you start rebasing.\u00a0 However, git pull requests do handle rebased changes.\u00a0 You can push -f to your own fork and the pull request will remove the old commits from the conversation and add the new ones at the bottom.<\/p>\n<h3>Merge into master<\/h3>\n<p>When my changes are ready, I can merge my branch back into master.\u00a0 However, I don&#8217;t need to make a merge commit if there&#8217;s only one commit to merge in.\u00a0 That would clutter up the logs.\u00a0 I can do this with a fast-forward merge:<\/p>\n<pre>git checkout master\r\ngit merge --ff add-email-to-install<\/pre>\n<p>Now I can close the ticket in our tracker with a direct link to my changes.<\/p>\n<p>Sometimes I might actually make multiple commits on a single topic branch.\u00a0 In this case I <em>would<\/em> want to retain the automatic merge commit.\u00a0 That is, I wouldn&#8217;t do a fast forward merge in the case of multiple commits:<\/p>\n<pre>git merge --no-ff add-email-to-install<\/pre>\n<p>I can then close the ticket with a link to the single merge commit that shows all changes introduced by the branch.<\/p>\n<h3>Fixups, for ninjas<\/h3>\n<p>If you follow this pattern you&#8217;ll become accustomed to frequently fixing up your topic branch. I created a ninja alias for it in ~\/.gitconfig like this:<\/p>\n<pre>[alias]\r\n\u00a0\u00a0\u00a0 ...\r\n\u00a0\u00a0\u00a0 fix = \"!f() { git commit -a -m \\\"fixup! $(git log -1 --pretty=format:%s)\\\" &amp;&amp; git rebase -i --autosquash HEAD~4; }; f\"<\/pre>\n<p>When on a topic branch with uncommitted changes I can then type:<\/p>\n<pre>git fix<\/pre>\n<p>That will automatically commit my change and pre-configure the rebase prompt to fold it into the last commit.<\/p>\n<p><strong>UPDATE:<\/strong> As pointed out in the comments, a quicker and simpler way to fix up and rebase just the <em>last<\/em> commit (i.e. not multiple commits) is:<\/p>\n<pre>[alias]\r\n\u00a0\u00a0\u00a0 ...\r\n\u00a0\u00a0\u00a0 fix = \"commit -a --amend -C HEAD\"<\/pre>\n<h3>Synchronization with master, for ninjas<\/h3>\n<p>If you&#8217;re on a project that has a lot of commit activity you&#8217;ll probably want to rebase your feature branch on top of master often.\u00a0 I added a ninja alias to ~\/.gitconfig for that too:<\/p>\n<pre>[alias]\r\n\u00a0\u00a0\u00a0 ...\r\n\u00a0\u00a0\u00a0 sync = \"!f() { echo Syncing $1 with master &amp;&amp; git checkout master &amp;&amp; git pull &amp;&amp; git checkout $1 &amp;&amp; git rebase master; }; f\"<\/pre>\n<p>When I&#8217;m on my feature branch and I want to synchronize it with all the latest changes on master, I type:<\/p>\n<pre>git sync add-email-to-install<\/pre>\n<p>The main benefit to syncing a branch before merging into master is that a fast-forward merge won&#8217;t create a new commit.\u00a0 This helps you safely delete work branches later on since it won&#8217;t look like you have un-merged changes.\u00a0 It&#8217;s also useful to do a last minute spot check before merging into master: do the tests still pass? do I need to adjust my SQL migration script? etc.<\/p>\n<p><strong>UPDATE:<\/strong> Fernando Takai posted a simpler version of this in the comments using <code>git checkout -<\/code> to go back to the last branch you were on. You can then simply type <code>git sync<\/code> from the branch. Thanks!<\/p>\n<h3>Why resort to all these ninja like git strategies?<\/h3>\n<ul>\n<li>Using git blame on a single line of code is more likely to give your team a full picture of all the reasons why that line of code was introduced. For this same reason, we at <a href=\"https:\/\/github.com\/mozilla\/zamboni\/\">addons.mozilla.org<\/a> always link to our bug tracker in each commit.<\/li>\n<li>Your commit log will have a high signal to noise ratio making it easier to skim when looking at a compare view between releases.<\/li>\n<li>Ninjas don&#8217;t make mistakes.\u00a0 Ever.<\/li>\n<\/ul>\n<h3>Random Notes<\/h3>\n<ul>\n<li>Kernel hackers frown on using rebase but that&#8217;s probably because many people are committing to the same files and it&#8217;s important to see what the original starting tree was when work on a new feature started.\u00a0 For web development, if two members on your team are working on the same line in the same file then your team isn&#8217;t communicating well enough.\u00a0 I rarely see conflicts on my team that aren&#8217;t resolved automatically by a three way merge.<\/li>\n<li>After committing to master you might discover a mistake.\u00a0 That&#8217;s fine, make a new commit.\u00a0 Be sure to <em>never fixup a commit on master<\/em> because everyone tracking master will be sad!<\/li>\n<li>Where do your fixed up commits go?\u00a0 They are still there but are detached from any branch and thus get deleted eventually by git&#8217;s garbage collector.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>When I first joined the webdev group at Mozilla I was a Mercurial refugee who had never used git or github. I was always daunted by git and suddenly I had to learn it really fast!\u00a0 Fast forward to today &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/\">Continue reading<\/a><\/p>\n","protected":false},"author":293,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,666,288],"tags":[],"coauthors":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Git: Using topic branches and interactive rebasing effectively - Mozilla Web Development<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"kumar303\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/\",\"url\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/\",\"name\":\"Git: Using topic branches and interactive rebasing effectively - Mozilla Web Development\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png\",\"datePublished\":\"2011-11-21T15:58:11+00:00\",\"dateModified\":\"2012-06-18T16:46:13+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/aa2b14e555e8a5fec38a51659b15e3c4\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage\",\"url\":\"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png\",\"contentUrl\":\"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/webdev\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Git: Using topic branches and interactive rebasing effectively\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/webdev\/\",\"name\":\"Mozilla Web Development\",\"description\":\"For make benefit of glorious tubes\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/webdev\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/aa2b14e555e8a5fec38a51659b15e3c4\",\"name\":\"kumar303\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/image\/a707ad1bf04083698e2b4a775a7492b7\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/059920b9daee1ece045f4031037ffb79?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/059920b9daee1ece045f4031037ffb79?s=96&d=mm&r=g\",\"caption\":\"kumar303\"},\"description\":\"Kumar hacks on Mozilla web services and tools for various projects, such as those supporting Firefox Add-ons. He hacks on lots of random open source projects too.\",\"sameAs\":[\"http:\/\/farmdev.com\/\",\"https:\/\/www.facebook.com\/kumar303\",\"https:\/\/x.com\/kumar303\"],\"url\":\"https:\/\/blog.mozilla.org\/webdev\/author\/kmcmillanmozilla-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Git: Using topic branches and interactive rebasing effectively - Mozilla Web Development","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/","twitter_misc":{"Written by":"kumar303","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/","url":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/","name":"Git: Using topic branches and interactive rebasing effectively - Mozilla Web Development","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/webdev\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage"},"image":{"@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage"},"thumbnailUrl":"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png","datePublished":"2011-11-21T15:58:11+00:00","dateModified":"2012-06-18T16:46:13+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/aa2b14e555e8a5fec38a51659b15e3c4"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#primaryimage","url":"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png","contentUrl":"http:\/\/blog.mozilla.org\/webdev\/files\/2011\/11\/github-code-review-example2.png"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/11\/21\/git-using-topic-branches-and-interactive-rebasing-effectively\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/webdev\/"},{"@type":"ListItem","position":2,"name":"Git: Using topic branches and interactive rebasing effectively"}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/webdev\/#website","url":"https:\/\/blog.mozilla.org\/webdev\/","name":"Mozilla Web Development","description":"For make benefit of glorious tubes","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/webdev\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/aa2b14e555e8a5fec38a51659b15e3c4","name":"kumar303","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/image\/a707ad1bf04083698e2b4a775a7492b7","url":"https:\/\/secure.gravatar.com\/avatar\/059920b9daee1ece045f4031037ffb79?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/059920b9daee1ece045f4031037ffb79?s=96&d=mm&r=g","caption":"kumar303"},"description":"Kumar hacks on Mozilla web services and tools for various projects, such as those supporting Firefox Add-ons. He hacks on lots of random open source projects too.","sameAs":["http:\/\/farmdev.com\/","https:\/\/www.facebook.com\/kumar303","https:\/\/x.com\/kumar303"],"url":"https:\/\/blog.mozilla.org\/webdev\/author\/kmcmillanmozilla-com\/"}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts\/2245"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/users\/293"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/comments?post=2245"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts\/2245\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/media?parent=2245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/categories?post=2245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/tags?post=2245"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/coauthors?post=2245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}