{"id":390,"date":"2013-03-28T14:05:32","date_gmt":"2013-03-28T11:05:32","guid":{"rendered":"http:\/\/www.held.org.il\/blog\/?p=390"},"modified":"2013-03-28T14:05:32","modified_gmt":"2013-03-28T11:05:32","slug":"navigating-through-the-git-history-like-a-boss","status":"publish","type":"post","link":"http:\/\/www.held.org.il\/blog\/2013\/03\/navigating-through-the-git-history-like-a-boss\/","title":{"rendered":"Navigating through the git history like a boss"},"content":{"rendered":"<p>[ If you're not into reading why I find git history useful, you may <a href=\"#tahles\">jump right into the command-line coolness!<\/a> ]<\/p>\n<p>I love reading git logs! First, because it reveals the people and processes behind software. Software is not just a bunch of code that works (or more commonly, doesn't work...) - it's also a bunch of people crafting something together for a long time. Not only adding features and fixing bugs, but they also refactor, do dirty tasks and ugly workarounds, explaining their motives in the commit messages.<\/p>\n<p>A second, more concrete reason - quick access to git history helps me make better software. It helps me find out when and how exactly a bug was introduced, learn whom to talk to about a certain change or code, or simply find a desired code snippet in a huge repository - even if it was already deleted. Am I stating the obvious here? I guess so! but I do believe that sometimes this tool is underestimated and underused.<br \/>\n<!--more--><\/p>\n<p>Of course, the better we know git's secrets, the more effective use of git history we could make. I'll try to share here some useful tricks I've collected in the recent years... I bet you know some; I believe you may still find some of them useful.<\/p>\n<p><a name=\"tahles\"><\/a>Alright, enough human communication - let the command-line part begin:<\/p>\n<h2>1. Find commits by their commit message - --grep<\/h2>\n<p>Impress your boss at how quickly you find this commit!<\/p>\n<pre lang=\"bash\">git log -p --grep \"nasty bug\"\r\n\r\n# Feeling lucky? \r\ngit show :\/'nasty bug'<\/pre>\n<h2>2. Search by commit content - -S<\/h2>\n<p>This one will show you only commits that contain the provided string in the commit content itself. Super useful!<\/p>\n<pre lang=\"bash\">git log -p -S 'Date.new'<\/pre>\n<h2>3. Search by author<\/h2>\n<p>You know who's responsible for this change you're looking for, so why not use this to ease the search?<\/p>\n<pre lang=\"bash\">git log -p --author='Linus Torvalds'\r\n\r\n# Can even use parts of the name or email:\r\ngit log -p --author=orvalds\r\ngit log -p --author=gmail.com<\/pre>\n<h2>4. Find by date<\/h2>\n<pre lang=\"bash\">git log -p --since=2013-01-01 --until=2012-02-01<\/pre>\n<h2>5. By path!<\/h2>\n<pre lang=\"bash\">git log -p -- path\/to\/file1 path\/to\/directory ...\r\n\r\n# Add --follow to follow changes through file renames:\r\ngit log -p --follow -- path\/to\/file1<\/pre>\n<h2>6. Search ALL branches<\/h2>\n<p>Lost something?<\/p>\n<pre lang=\"bash\">git log -S 'populate_database' --all<\/pre>\n<h2>7. Putting (some of) it all together<\/h2>\n<p>I actually find such commands useful in practice.<\/p>\n<pre lang=\"bash\">git log -p --author=linus --since=2012-06-01 --until=2013-01-01 --grep fix -S 'Date.new' -- that_directory\/<\/pre>\n<h2>8. A few useful revision-range tricks<\/h2>\n<h3>a. What's new in my branch compared to remote?<\/h3>\n<pre lang=\"bash\">git log -p origin\/master..master\r\n\r\n# But I like the following syntax better; it's exactly the same but self-explanatory:\r\n# all commits of master branch that are not contained in origin\/master branch. \r\ngit log -p master ^origin\/master\r\n\r\n# Also possible to put multiple arguments\r\ngit log -p master ^origin\/master ^my_github\/master<\/pre>\n<p>(Note: I've noticed that zsh needs the '^' character to be escaped!)<\/p>\n<h3>b. 3-dots operator: symmetric difference<\/h3>\n<p>The less-widely-known-but-very-useful 3-dots operator, shows any commit that is in any of the branches but not in both:<\/p>\n<pre lang=\"bash\">git log -p mybranch...master\r\n\r\n# --cherry-pick is often useful to avoid seeing \"duplicate commits\". \r\n# common when cherry-picking, where commits identical content get \r\n# different hashes.\r\ngit log -p --cherry-pick mybranch...master<\/pre>\n<h2>Read more!<\/h2>\n<pre lang=\"bash\">git help log\r\ngit help revisions\r\ngit help blame<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>[ If you&#8217;re not into reading why I find git history useful, you may jump right into the command-line coolness! ] I love reading git logs! First, because it reveals the people and processes behind software. Software is not just a bunch of code that works (or more commonly, doesn&#8217;t work&#8230;) &#8211; it&#8217;s also a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[195],"tags":[198,194],"_links":{"self":[{"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/posts\/390"}],"collection":[{"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/comments?post=390"}],"version-history":[{"count":0,"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/posts\/390\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/media?parent=390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/categories?post=390"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.held.org.il\/blog\/wp-json\/wp\/v2\/tags?post=390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}