<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Nuclear Squid</title>
    <description>Musings on technology.
</description>
    <link>https://nuclearsquid.com/</link>
    <atom:link href="https://nuclearsquid.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 03 Oct 2023 11:20:49 +0200</pubDate>
    <lastBuildDate>Tue, 03 Oct 2023 11:20:49 +0200</lastBuildDate>
    <generator>Jekyll v4.1.1</generator>
    
      <item>
        <title>macOS Terminal cheat sheet</title>
        <description>&lt;p&gt;The Terminal on macOS offers quite an amount of functionality, but most of it is hard to discover unless you already know what you’re looking for. So here’s a quick cheat sheet explaining unique functions with their corresponding key combos:&lt;/p&gt;

&lt;h2 id=&quot;marks&quot;&gt;Marks&lt;/h2&gt;

&lt;p&gt;Marks allow you to mark certain lines in the output, and allow you to jump between different parts of the output.&lt;/p&gt;

&lt;p&gt;By default, every time you hit enter on your prompt, Terminal will automatically insert a mark for you. You can configure this in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Edit&lt;/code&gt; menu, under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Marks&lt;/code&gt; with the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Automatically Mark Prompt Lines&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Marks are visualised in the Terminal window as light grey square brackets (They are not, however, part of the output).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-⬆&lt;/code&gt;: Jump to previous mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-⬇&lt;/code&gt;: Jump to next mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-A&lt;/code&gt;: Selects the output between the current marks&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Enter&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;, and will always create a mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-Enter&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;, but will never create a mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-U&lt;/code&gt;: Create mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-U&lt;/code&gt;: Remove mark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-L&lt;/code&gt;: Clear screen to previous mark&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;bookmarks&quot;&gt;Bookmarks&lt;/h2&gt;

&lt;p&gt;Similar to marks, they can optionally be named, and are more useful to denote larger sections of the output. They are denoted by light grey bars.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-M&lt;/code&gt;: Insert Bookmark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-U&lt;/code&gt;: Mark current line as bookmark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-Option-M&lt;/code&gt;: Insert named bookmark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-⬆&lt;/code&gt;: Jump to previous bookmark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-⬇&lt;/code&gt;: Jump to next bookmark&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-L&lt;/code&gt;: Clear to previous bookmark&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;panes&quot;&gt;Panes&lt;/h2&gt;

&lt;p&gt;View different parts of the scrollback buffer of the same terminal.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-D&lt;/code&gt;: Split window into panes&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-D&lt;/code&gt;: close split pane&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-K&lt;/code&gt;: Clear everything&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-K&lt;/code&gt;: Clear scroll back (everything except what you see on the screen)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-O&lt;/code&gt;: Toggle use of option as meta key&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Ctrl-V&lt;/code&gt;: Paste escaped text. Useful for pasting e.g. paths containing whitespace.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-Option-C&lt;/code&gt;: Copy as plain text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Option-PageUp&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PageDown&lt;/code&gt;: Scroll one line up/down&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-[&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;: Switch between windows&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd-Shift-[&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;: Switch between tabs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Some of this I learned from mjtsai’s post &lt;a href=&quot;http://mjtsai.com/blog/2016/09/26/mac-terminal-tips/&quot;&gt;Mac Terminal Tips&lt;/a&gt;, which is a great jumping off point for further interesting things the Terminal can do)&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Oct 2016 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/macos-terminal-cheat-sheet/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/macos-terminal-cheat-sheet/</guid>
        
        
      </item>
    
      <item>
        <title>Rust Presentation at Vienna.rb</title>
        <description>&lt;p&gt;A presentation I gave at the &lt;a href=&quot;http://www.meetup.com/vienna-rb/events/159629132/&quot;&gt;Vienna.rb Meetup in February 2014&lt;/a&gt;:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;a68f628071f701314bf35aef2655508f&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Thu, 06 Feb 2014 00:00:00 +0100</pubDate>
        <link>https://nuclearsquid.com/writings/rust-presentation/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/rust-presentation/</guid>
        
        
        <category>Rust</category>
        
        <category>Presentations</category>
        
        <category>Vienna.rb</category>
        
      </item>
    
      <item>
        <title>How to become a Better Developer</title>
        <description>&lt;p&gt;You probably know the feeling. You’re writing a piece of code, and just by looking at it, you know it could be better – but you don’t know how. You have that feeling that the right solution is just around the corner, if only you could reach it… but you don’t, and you have to live with whatever you’ve got. You have to live with the knowledge you were not good enough to write better code.&lt;/p&gt;

&lt;p&gt;This happens especially if you’ve just left the beginner stage behind, and are slowly advancing through the intermediate stage. Many plateaus await you, frustrating you in your quest for progress. Some days, it seems like you’ve hit your limits, the very best you can do, and that you cannot go any further.&lt;/p&gt;

&lt;p&gt;But there are things you can do to help yourself. I’d like to tell you about a few.&lt;/p&gt;

&lt;h3 id=&quot;challenge-yourself&quot;&gt;Challenge yourself&lt;/h3&gt;

&lt;p&gt;Similar to training a muscle, your skills won’t grow when you keep repeating the same things over and over. So it is important that you expose yourself to new concepts and ideas. Often, you’ll feel out of your element, and like the biggest n00b on the planet. And that’s ok. If it’s not hard, if it doesn’t suck, you probably won’t learn much from it. Become comfortable with your &lt;a href=&quot;http://zenhabits.net/discomfort/&quot; title=&quot;Discomfort Zone: How to Master the Universe&quot;&gt;Discomfort Zone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Expose yourself to new ideas. Read about something you do not yet quite understand. Listen to podcasts about topics you do not know much about. Watch screencasts about things you’ve only dreamed of.&lt;/p&gt;

&lt;p&gt;Ask other people about books, blogs, screencasts, or podcasts they recommend. But also always ask them why they recommend them. What is right for them may not be right for you.&lt;/p&gt;

&lt;p&gt;I like &lt;a href=&quot;http://rubyrogues.com/&quot; title=&quot;Ruby Rogues&quot;&gt;Ruby Rogues&lt;/a&gt;, &lt;a href=&quot;http://www.rubytapas.com/&quot; title=&quot;Ruby Tapas&quot;&gt;Avdi Grimm’s Ruby Tapas&lt;/a&gt;, &lt;a href=&quot;http://realtalk.io&quot; title=&quot;Real Talk - The Only Technical Podcast&quot;&gt;Real Talk&lt;/a&gt;, &lt;a href=&quot;http://vimcasts.org&quot; title=&quot;Vimcasts&quot;&gt;Vimcasts&lt;/a&gt;, &lt;a href=&quot;http://www.cleancoders.com/codecast/bawch-episode-1/show&quot;&gt;Build an App with Cory Haines&lt;/a&gt; and &lt;a href=&quot;https://www.destroyallsoftware.com&quot; title=&quot;Destroy All Software&quot;&gt;Gary Bernhardt’s Destroy All Software&lt;/a&gt;. Each one of these has exposed me to new ideas, or a new way of doing things that I hadn’t know of or considered before.&lt;/p&gt;

&lt;p&gt;But even more important, do new stuff. Just collecting information in your head is not enough, you also have to implement it. Want to learn functional programming? Go learn Haskell. Want to work in a statically typed language? Learn Scala. Always wanted to know more about the actor model? Learn Erlang.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Here’s the thing: After that initial explosion of cognitive growth, they noticed a decline in both cortical thickness, as well as the amount of glucose used during that task. However, they remained just as good at Tetris; their skill did not decrease. The brain scans showed less brain activity during the game-playing, instead of more, as in the previous days. Why the drop? Their brains got more efficient. Once their brain figured out how to play Tetris, and got really good at it, it got lazy. It didn’t need to work as hard in order to play the game well, so the cognitive energy and the glucose went somewhere else instead.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;http://blogs.scientificamerican.com/guest-blog/2011/03/07/you-can-increase-your-intelligence-5-ways-to-maximize-your-cognitive-potential/&quot;&gt;Andrea Kuszewski, “You can increase your intelligence: 5 ways to maximize your cognitive potential”&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then write programs in those languages. They don’t have to be things that will actually be put in production, but you should write non-trivial programs that do something useful (ie., anything but printing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;Hello World&quot;&lt;/code&gt;).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You are functionally blind when you only have book knowledge.&lt;/p&gt;

  &lt;p&gt;~ &lt;a href=&quot;http://blog.8thlight.com/chong-kim/2013/09/26/using-katas-to-improve.html&quot; title=&quot;Using Katas To Improve&quot;&gt;Chong Kim&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;study-the-masters--and-mastering&quot;&gt;Study the masters – and mastering&lt;/h3&gt;

&lt;p&gt;Amy Hoy’s post &lt;a href=&quot;http://unicornfree.com/2012/why-blacksmiths-are-better-at-startups-than-you&quot; title=&quot;Why Blacksmiths are Better at Startups than You&quot;&gt;“Why Blacksmiths are Better at Startups than You”&lt;/a&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; contains many great lessons about mastery, apprenticeship, and how we often sabotage ourselves on our path to getting better.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://peepcode.com/screencasts/play-by-play&quot;&gt;PeepCode’s Play by Play series&lt;/a&gt; shows how masters work on a given exercise, telling you about their thought process and explaining their decisions as they go along.&lt;/p&gt;

&lt;p&gt;And, if you can, find a mentor, someone who can guide you, show you the way, and provide you with useful criticism that will let you grow.&lt;/p&gt;

&lt;h3 id=&quot;learn-the-classics&quot;&gt;Learn the classics&lt;/h3&gt;

&lt;p&gt;Languages and frameworks come and go, but the classics are forever.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You might call some of these things “computer science”, but many of the best programmers I know have no formal training in such. These things can be learned by anybody, many of them are learned best in a hands-on environment.&lt;/p&gt;

  &lt;p&gt;Investing your time learning things like networking, concurrency, regexes, or system programming will not go out of style in your lifetime.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;http://www.jstorimer.com/pages/newsletter&quot;&gt;Jesse Storimer, in his “Working With #{code}” newsletter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Languages and frameworks are only tools, a means to an end. Understand why those tools exist, and why they work the way they do, and you will gain a deeper understanding of how things work.&lt;/p&gt;

&lt;p&gt;And they will set you apart from others who define themselves as Ruby/Python/PHP/JavaScript developers. Restricting yourself to one language or framework means limiting your horizon to many other things out there.&lt;/p&gt;

&lt;h3 id=&quot;practice-mindfully&quot;&gt;Practice mindfully&lt;/h3&gt;

&lt;p&gt;Sites like &lt;a href=&quot;http://exercism.io&quot; title=&quot;Exercism.io&quot;&gt;Exercism.io&lt;/a&gt; or &lt;a href=&quot;http://www.codewars.com/&quot; title=&quot;Codwars&quot;&gt;Code Wars&lt;/a&gt; present you with programming challenges in various languages that allow you to “exercise” in a very defined way. &lt;a href=&quot;http://exercism.io&quot; title=&quot;Exercism.io&quot;&gt;Exercism.io&lt;/a&gt; is especially great because its emphasis is on getting and giving feedback, forcing you to think and argue about your design decisions. This can be very enlightening even with apparently very simple exercises.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.8thlight.com/chong-kim/2013/09/26/using-katas-to-improve.html&quot; title=&quot;Using Katas To Improve&quot;&gt;Using Katas to Improve Yourself&lt;/a&gt; is another possibility to train your programming abilities, while at the same time picking up a new language or framework.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://rubyrogues.com/054-rr-coding-exercises-quizzes-and-katas/&quot; title=&quot;054 RR Coding Exercises, Quizzes, and Katas&quot;&gt;The Ruby Rogues episode on coding exercises, quizzes and katas&lt;/a&gt; also contains useful information on that topic.&lt;/p&gt;

&lt;h3 id=&quot;mind-your-body&quot;&gt;Mind your body&lt;/h3&gt;

&lt;p&gt;Go outside and get fresh air. Sleep more (about 7 hours seems to be the right amount for most people). Work out, even if it’s only 15 minutes every other day. And &lt;a href=&quot;http://zenhabits.net/meditate/&quot; title=&quot;How to Meditate Daily&quot;&gt;start meditating for 2 minutes each day&lt;/a&gt;. Doing these things will improve every area of your life, not just your programming.&lt;/p&gt;

&lt;h3 id=&quot;the-key&quot;&gt;The Key&lt;/h3&gt;

&lt;p&gt;Always remember that the biggest factor that determines your success is not intelligence, or talent. &lt;a href=&quot;http://www.bakadesuyo.com/2012/11/secret-success-not-giving-up/&quot;&gt;Grit, the perseverance and passion for long-term goals&lt;/a&gt;, and your attitude towards getting better are what determines your path ahead.&lt;/p&gt;

&lt;h3 id=&quot;and-finally&quot;&gt;And finally&lt;/h3&gt;

&lt;p&gt;Something to meditate on:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;One day a monk visited Master Wq, and inquired, “Master, how will my code be different when I have mastered Vim?”&lt;/p&gt;

  &lt;p&gt;Master Wq answered, “Before Vim: declare, define, process, print. After Vim: declare, define, process, print.”&lt;/p&gt;

  &lt;p&gt;~ &lt;a href=&quot;http://blog.sanctum.geek.nz/vim-koans/&quot;&gt;Vim Koans&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h3&gt;

&lt;p&gt;Thanks to eclubb, Tekhne, augiedb, michael, newton10471, and markijbema of the RubyRouges Parley forum for suggestions and feedback.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Even though the post discusses mastery in the context of a business and startup founders, its lessons are easily applicable to mastery in general. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 12 Oct 2013 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/how-to-become-a-better-developer/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/how-to-become-a-better-developer/</guid>
        
        
      </item>
    
      <item>
        <title>A Very Short Overview of Vagrant</title>
        <description>&lt;p&gt;A presentation I gave at the &lt;a href=&quot;http://www.meetup.com/vienna-rb/events/111534092/&quot;&gt;Vienna.rb Meetup in July 2013&lt;/a&gt;:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;fe6f0650d1ef0130c0b5026b4eb85e5a&quot; data-ratio=&quot;1.6&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Thu, 18 Jul 2013 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/a-very-short-overview-vagrant/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/a-very-short-overview-vagrant/</guid>
        
        
        <category>Presentations</category>
        
        <category>Vienna.rb</category>
        
      </item>
    
      <item>
        <title>n Things You Probably Didn't Know About PostgreSQL</title>
        <description>&lt;p&gt;A presentation I gave at the &lt;a href=&quot;http://www.meetup.com/vienna-rb/events/111533282/&quot;&gt;Vienna.rb Meetup in June 2013&lt;/a&gt;:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;79d9be00b106013071d432c4d3b0deea&quot; data-ratio=&quot;1.6&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Thu, 06 Jun 2013 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/n-things-you-probably-didnt-know-about-postgres/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/n-things-you-probably-didnt-know-about-postgres/</guid>
        
        
        <category>Presentations</category>
        
        <category>PostgreSQL</category>
        
        <category>Vienna.rb</category>
        
      </item>
    
      <item>
        <title>Rails Security Primer presentation</title>
        <description>&lt;p&gt;A small presentation I gave at the &lt;a href=&quot;http://www.meetup.com/vienna-rb/events/102682372/&quot;&gt;Vienna.rb Meetup in March 2013&lt;/a&gt;:&lt;/p&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;b58868c069660130145e123138156442&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Thu, 14 Mar 2013 00:00:00 +0100</pubDate>
        <link>https://nuclearsquid.com/writings/rails-security-primer/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/rails-security-primer/</guid>
        
        
        <category>presentations</category>
        
        <category>Vienna.rb</category>
        
      </item>
    
      <item>
        <title>Sharing history in zsh</title>
        <description>&lt;p&gt;One feature of any shell that is immensly useful is the history. Any command you made gets recorded, and you can then retrieve it later on with various commands (my favorite: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-R&lt;/code&gt;, which allows you to search through your history).&lt;/p&gt;

&lt;p&gt;At any given time, I usually have anywhere between 10 and 20 terminals open somewhere (not counting remote sessions). Thanks to zsh I can share every command I enter between all those terminal after I enter it and make it accessible via the history.&lt;/p&gt;

&lt;p&gt;This means I no longer have to remember which terminal I entered my command in, all I have to do is search the history.&lt;/p&gt;

&lt;h1 id=&quot;how-to-enable-this&quot;&gt;How to enable this&lt;/h1&gt;

&lt;p&gt;In your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Appends every command to the history file once it is executed&lt;/span&gt;
setopt inc_append_history
&lt;span class=&quot;c&quot;&gt;# Reloads the history whenever you use it&lt;/span&gt;
setopt share_history&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</description>
        <pubDate>Fri, 27 Apr 2012 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/shared-history-in-zsh/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/shared-history-in-zsh/</guid>
        
        
      </item>
    
      <item>
        <title>REPORTTIME in zsh</title>
        <description>&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REPORTTIME&lt;/code&gt; is a nifty feature of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;. If you set it to a non-negative value, then every time, any command you run that takes longer than the value you set it to in seconds, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; will print usage statistics afterwards as if you had run the command prefixed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, for example, if we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rake&lt;/code&gt; to rebuild any out of date files in Rubinius, we get this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~/Development/Rubinius ☺ » rake 
[ … Lots of output …]

Finished in 136.926808 seconds

3866 files, 21497 examples, 59187 expectations, 0 failures, 0 errors
rake  160.78s user 26.49s system 81% cpu 3:50.20 total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(Yes, my prompt has a smiley in it. It turns sad and red when the exit status is non-zero)&lt;/p&gt;

&lt;h2 id=&quot;how-to-enable-this&quot;&gt;How to enable this&lt;/h2&gt;

&lt;p&gt;Since this only makes sense in interative shells, I set this value in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Report CPU usage for commands running longer than 10 seconds
REPORTTIME=10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(&lt;a href=&quot;https://github.com/cypher/dotfiles/blob/e5478f189b8f7c116cf1abe4be83c96633330fe5/zshrc#L25&quot; title=&quot;my zshrc on GitHub&quot;&gt;See this on GitHub&lt;/a&gt;)&lt;/p&gt;

</description>
        <pubDate>Thu, 26 Apr 2012 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/reporttime-in-zsh/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/reporttime-in-zsh/</guid>
        
        
      </item>
    
      <item>
        <title>Extending a PostgreSQL Enum Type</title>
        <description>&lt;p&gt;PostgreSQL supports custom enum types, which is awesome. However, extending them is kind of a pain, since there is no command to just add a new value to the enum.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;http://stackoverflow.com/questions/1771543/postgresql-updating-an-enum-type&quot; title=&quot;StackOverflow: PostgreSQL - Updating an Enum Type&quot;&gt;this StackOverflow answer&lt;/a&gt;, there are two alternate ways to still get what you want. One works by modifying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pg_enum&lt;/code&gt;, which strikes me as a bit of a bad idea, since those tables are under Postgres’ direct control.&lt;/p&gt;

&lt;p&gt;The other one works by adding a new type, and adding a new column, then copying over all the old values, and finally dropping the old columns and types (via &lt;a href=&quot;http://stackoverflow.com/users/333881/taksofan&quot;&gt;taksofan&lt;/a&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;RENAME&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- &quot;Extend&quot; enum_type with a new value: d&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ENUM&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'b'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'c'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'d'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_table&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;RENAME&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the_enum_column&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_table&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the_enum_column&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_table&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the_enum_column&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_table&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works well enough for my purposes, but will probably not do so well with very large tables.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.depesz.com/index.php/2010/10/27/waiting-for-9-1-adding-values-to-enums/&quot;&gt;PostgreSQL 9.1 will be able to extend enum types with much less fuss&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'new_value'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BEFORE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'old_value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;update-2011-11-08&quot;&gt;Update 2011-11-08&lt;/h2&gt;

&lt;p&gt;If you want to change the enum type used in a large table, then the method described above will very likely take a long time to finish.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://amd.co.at/&quot;&gt;Michael Renner&lt;/a&gt; and RhodiumToad on &lt;a href=&quot;irc://freenode.net/postgresql&quot; title=&quot;#postgresql on Freenode&quot;&gt;Freenode/#postgresql&lt;/a&gt; pointed out two different ways speed up this process.&lt;/p&gt;

&lt;h3 id=&quot;the-faster-safe-way&quot;&gt;The faster, safe way&lt;/h3&gt;

&lt;p&gt;The first one works like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You create your new, extended enum type&lt;/li&gt;
  &lt;li&gt;You alter your column to use that new enum type. This requires a single bulk rewrite of the table, but this is much faster than copying over the old values into a new value.&lt;/li&gt;
  &lt;li&gt;Drop the old value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or, in SQL:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;RENAME&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ENUM&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'b'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'c'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'d'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_table&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COLUMN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the_enum_column&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_old_enum_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;the-even-faster-but-possibly-very-dangerous-way&quot;&gt;The even faster, but possibly very dangerous, way&lt;/h3&gt;

&lt;p&gt;The second one is decidedly more dangerous, so make sure you test everything thouroghly.&lt;/p&gt;

&lt;p&gt;First, for this to work, you must ensure that no OID wraparound has happened. How can you tell if an OID wraparound has happened? Execute this query:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TEMP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regclass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then make sure if the returned OID is larger than both the smallest and largest value of the enum.&lt;/p&gt;

&lt;p&gt;And secondly, this messes around in PostgreSQL internals, so there might be other side effects. Use this at your own risk.&lt;/p&gt;

&lt;p&gt;Here goes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;c1&quot;&gt;-- PostgreSQL 9&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pg_enum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enumtypid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;VALUES&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'enum_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'d'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- PostgreSQL 10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- Here, we set enumsortorder to be one higher than the highest sort order for the type&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pg_enum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enumtypid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumsortorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;VALUES&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'enum_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'d'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;MAX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enumsortorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pg_enum&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumtypid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'enum_type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sun, 15 May 2011 00:00:00 +0200</pubDate>
        <link>https://nuclearsquid.com/writings/extending-a-postgresql-enum-type/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/extending-a-postgresql-enum-type/</guid>
        
        
        <category>postgresql</category>
        
      </item>
    
      <item>
        <title>A few of my Git tricks, tips and workflows</title>
        <description>
&lt;p&gt;&lt;a href=&quot;https://cocoaheads.at/2011/03/git-tips-tricks-und-workflows/&quot; title=&quot;Einige meiner Git Tips, Tricks und Arbeitsabläufe&quot;&gt;&lt;em&gt;Note: A german translation is available here&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is based on a talk I gave at the &lt;a href=&quot;http://cocoaheads.at/vorträge&quot; title=&quot;Cocoaheads Austria&quot;&gt;18th Cocoaheads Meetup Vienna (CHW018)&lt;/a&gt; on Feb 17th, 2011. It is an annotated tour of my Git config, Git related scripts and commands, and various other tips and tricks I picked up over the years. You can find most of these things in my &lt;a href=&quot;https://github.com/cypher/dotfiles&quot; title=&quot;cypher/dotfiles on GitHub&quot;&gt;dotfiles&lt;/a&gt; repo, as well with a lot of other stuff, like parts of my Zsh config. Patches welcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Some of these tricks and tips are specific to my setup (Mac OS X Snow Leopard, Git 1.7.4) and workflow(s), and might not quite work for you as described. I also assume you have basic knowledge of the command line.&lt;/p&gt;

&lt;h1 id=&quot;the-basics&quot;&gt;The Basics&lt;/h1&gt;

&lt;h3 id=&quot;getting-help&quot;&gt;Getting Help&lt;/h3&gt;

&lt;p&gt;No matter what you’re doing with Git, there’s always some kind of documentation that can help you out. But you should know where to get what. There are basically two ways on the command line.&lt;/p&gt;

&lt;p&gt;The first one is typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git &amp;lt;command&amp;gt; -h&lt;/code&gt; (replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;command&amp;gt;&lt;/code&gt; with the command in question of course), and Git will print a short overview of the call syntax as well as the most important options for you.&lt;/p&gt;

&lt;p&gt;The second one is having a look at the manpages themselves. The fastest way to get to them is by typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git help &amp;lt;command&amp;gt;&lt;/code&gt;, and git will open them for you. They are more thorough, but aren’t for the faint of heart either.&lt;/p&gt;

&lt;p&gt;On the web, there are a few more options. The &lt;a href=&quot;http://git-scm.com/documentation&quot; title=&quot;Git documentation&quot;&gt;Git Homepage&lt;/a&gt; lists quite a few introductions, tutorials, guides as well as online books that can help you out.&lt;/p&gt;

&lt;h3 id=&quot;git-autocompletion-for-your-shell&quot;&gt;Git Autocompletion for your shell&lt;/h3&gt;

&lt;p&gt;I use Git primarily from the command line. Luckily, enabling the Git completion for both Bash and Zsh is quite easy if you used &lt;a href=&quot;http://mxcl.github.com/homebrew&quot; title=&quot;Homebrew: The missing package manager for OS X&quot;&gt;Homebrew&lt;/a&gt; to install Git. Simply add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source `brew --prefix git`/etc/bash_completion.d/git-completion.bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you got Git some other way, check if that includes the completion file. If not, you can always clone the &lt;a href=&quot;http://git.kernel.org/?p=git/git.git;a=summary&quot; title=&quot;git.git&quot;&gt;git repo&lt;/a&gt;, and copy/link it from there.&lt;/p&gt;

&lt;p&gt;If you use Zsh, like me, there’s a bit more involved. Add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt; (adjust as necessary for your installation method):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Enable bash completion for git
# This allows git-completion to work properly
autoload bashcompinit
bashcompinit

source `brew prefix`/etc/git-completion.d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Update 2011-04-05:&lt;/em&gt; If you’re using a newer ZSH (I’ve tested this with 4.3.9), then you can skip all of the above, as Git completion will automagically work for you (if you already have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload -U compinit &amp;amp;&amp;amp; compinit&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If your version of ZSH is older, you can &lt;a href=&quot;http://zsh.git.sourceforge.net/git/gitweb.cgi?p=zsh/zsh;a=blob_plain;f=Completion/Unix/Command/_git;hb=HEAD&quot;&gt;download the git completion from the ZSH repository&lt;/a&gt; (&lt;a href=&quot;http://news.ycombinator.com/item?id=2411006&quot;&gt;h/t graywh on Hacker News&lt;/a&gt;)&lt;/p&gt;

&lt;h3 id=&quot;alias-git-to-g&quot;&gt;Alias git to ‘g’&lt;/h3&gt;

&lt;p&gt;I also alias &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt;, saving me 66% on typing time! Also, I’m lazy. Add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alias g='git'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, you’ll probably also want to have the Git Autocompletion when you’re using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt; as well. Add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Autocomplete for 'g' as well
complete -o default -o nospace -F _git g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;git-config1&quot;&gt;git-config(1)&lt;/h3&gt;

&lt;p&gt;In here, you can store all the global Git configuration settings. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitconfig&lt;/code&gt; file uses the INI file format to store settings, but you can also set (and get) all values by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config&lt;/code&gt;.
The most basic settings you should do are your name and eMail, both of which are included in every commit you make:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global user.name &quot;Markus Prinz&quot;
git config --global user.email &quot;markus.prinz@nuclearsquid.com&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not that I’m telling you how to run your life or anything, but you probably want use your own name and eMail address instead of mine.&lt;/p&gt;

&lt;p&gt;Over time, you will accumulate your own set of configs that tweak Git to your liking. Here are a few of my settings that I find very useful:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Allow all Git commands to use colored output, if possible&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global color.ui auto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable the advice shown by Git when you attempt to push something that’s not fast forward-able&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global advice.pushNonFastForward false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable “how to stage/unstage/add” hints given by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global advice.statusHints false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tell Git which whitespace problems it should recognize, namely any whitespace at the end of a line, as well as mixed spaces and tabs:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global core.whitespace trailing-space,space-before-tab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;See the man page for more possible options on this.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; to do basic rename and copy detection:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global diff.renames copies
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tell &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; to use mnemonic prefixes (&lt;strong&gt;i&lt;/strong&gt;ndex, &lt;strong&gt;w&lt;/strong&gt;ork tree, &lt;strong&gt;c&lt;/strong&gt;ommit, &lt;strong&gt;o&lt;/strong&gt;bject) instead of the standard &lt;strong&gt;a&lt;/strong&gt; and &lt;strong&gt;b&lt;/strong&gt; notation:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global diff.mnemonicprefix true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When branching off a remote branch, automatically let the local branch track the remote branch:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global branch.autosetupmerge true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When pushing without giving a refspec, push the current branch to its upstream branch. See the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config&lt;/code&gt; man page for more possible options.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global push.default tracking
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable the recording of resolved conflicts, so that identical hunks can be resolved automatically later on.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global rerere.enabled true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You may also want to investigate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rerere.autoupdate&lt;/code&gt; setting.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Always show a diffstat at the end of a merge:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global merge.stat true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you’ll notice that for each and every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config&lt;/code&gt; I used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--global&lt;/code&gt; option. The reason for that is that Git not only looks at your global gitconfig (located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt;), but also a repository-specific config (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/config&lt;/code&gt;). So you can customize all these settings for each of your repository to your liking, just run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config&lt;/code&gt; command in your repository without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--global&lt;/code&gt; flag.&lt;/p&gt;

&lt;h3 id=&quot;gitignore5&quot;&gt;gitignore(5)&lt;/h3&gt;

&lt;p&gt;You don’t want to commit all your files into your repository. Things like temporary files, logs, configurations that are specific to a computer, files that are for testing only, private keys for code signing or files that can be easily regenerated all don’t belong in your repository. However, they will still show up whenever you type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;, even though they are purely noise at that point.&lt;/p&gt;

&lt;p&gt;For this reason you can specify what files you want Git to ignore in a special file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;. Placed at the root of the repository, it contains &lt;a href=&quot;http://en.wikipedia.org/wiki/Glob_(programming)&quot; title=&quot;Glob Patterns&quot;&gt;glob patterns&lt;/a&gt; specifying all the files you want Git to ignore. Any file (and directory) matched by these globs won’t show up in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt;, and if you try to add them via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt;, Git will refuse to do so (you can still add them by specifying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; flag when adding).&lt;/p&gt;

&lt;p&gt;For example, Rails 3 projects use the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; by default:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.bundle
db/*.sqlite3
log/*.log
tmp/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells Git to ignore the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bundle&lt;/code&gt; directory, all files ending in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sqlite3&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;db&lt;/code&gt; directory, all the logs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt;, and everything in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmp&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Depending on what kind of project you’re working on, you’ll want to specify your own patterns. To save the work, &lt;a href=&quot;https://github.com/github/gitignore&quot;&gt;GitHub has a gitignore repository with glob patterns for many programming languages, frameworks and platforms&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are also &lt;a href=&quot;http://cocoaheads.tumblr.com/post/1350304132/gitignore-template-for-xcode3-4&quot;&gt;Xcode 3 &amp;amp; 4 specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; templates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, you can also tell Git to use a global &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; file, so you can exclude common files or ones that are specific to your platform. I keep mine at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitignore&lt;/code&gt;, and it contains excludes like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.DS_Store&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Icon?&lt;/code&gt;. Now all you need to do is tell git where it can find that file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global core.excludesfile '~/.gitignore'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you’ll never have to worry about any of these files showing up in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt; output any more.&lt;/p&gt;

&lt;h3 id=&quot;gitattributes5&quot;&gt;gitattributes(5)&lt;/h3&gt;

&lt;p&gt;This file allows you to specify attributes for given paths. It’s not a feature you’ll need often, but it can be incredibly handy.&lt;/p&gt;

&lt;p&gt;For example, in Rails projects, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;db/schema.rb&lt;/code&gt; file can often lead to merge conflicts that are easily resolved by figuring out which file is the most recent once, and then use that entire file as the resolution. But instead of having to do that by hand every time, we can tell Git to do it for us.&lt;/p&gt;

&lt;p&gt;First, you’ll need to add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[merge &quot;railsschema&quot;]
        name = newer Rails schema version
        driver = &quot;ruby -e '\n\
                system %(git), %(merge-file), %(--marker-size=%L), %(%A), %(%O), %(%B)\n\
                b = File.read(%(%A))\n\
                b.sub!(/^&amp;lt;+ .*\\nActiveRecord::Schema\\.define.:version =&amp;gt; (\\d+). do\\n=+\\nActiveRecord::Schema\\.define.:version =&amp;gt; (\\d+). do\\n&amp;gt;+ .*/) do\n\
                  %(ActiveRecord::Schema.define(:version =&amp;gt; #{[$1, $2].max}) do)\n\
                end\n\
                File.open(%(%A), %(w)) {|f| f.write(b)}\n\
                exit 1 if b.include?(%(&amp;lt;)*%L)'&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This specifies a new merge strategy called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;railsschema&lt;/code&gt;, along with the necessary command that Git needs to execute to resolve conflicts. The command itself is just a piece of Ruby code that figures out which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;schema.rb&lt;/code&gt; is the most recent one.&lt;/p&gt;

&lt;p&gt;Then, in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitattributes&lt;/code&gt; file, add the following line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;db/schema.rb merge=railsschema
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells Git than whenever it is merging &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;db/schema.rb&lt;/code&gt;, it should use our custom merge strategy instead of the default one. And we won’t ever have to manually merge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;schema.rb&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;You can also use this file to specify which end-of-line conversions Git should perform for certain file types, or files that it should treat as binary files. See the man page for more details.&lt;/p&gt;

&lt;h3 id=&quot;githooks5&quot;&gt;githooks(5)&lt;/h3&gt;

&lt;p&gt;Every time Git does something, you usually have the option of taking an action before or after Git has done its bit. An example of this would be a pre-commit hook, that you could use to prevent a commit from happening according to some custom criteria.&lt;/p&gt;

&lt;p&gt;All hooks are simple executable files, and can be written in whatever way you want to. I usually use basic shell script for simple stuff, and Ruby for the more complex hooks.&lt;/p&gt;

&lt;p&gt;Each Git repository contains a number of sample hooks under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/hooks/&lt;/code&gt;. To activate a hook, create or link the script/program to the hook name you wish to use in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/hooks/&lt;/code&gt;, and make sure it is executable.&lt;/p&gt;

&lt;p&gt;Hooks may get certain parameters that can help them determine what has happened. For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post-checkout&lt;/code&gt; hook gets the ref of the previous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt;, the ref of the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt;, and a flag indicating wether the checkout was due to changing branches.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/githooks.html&quot; title=&quot;githooks(5)&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;githooks(5)&lt;/code&gt;&lt;/a&gt; man page lists all available hooks, but the ones you’ll probably be interested in most of the time are these:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre-commit&lt;/code&gt;: This hook is executed before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt; creates a new commit. If this hook returns a non-zero status code, the commit is aborted. Very useful to prevent people from checking in stuff they shouldn’t (like passwords), or performing things like syntax checks to ensure that only valid code is being checked in.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post-commit&lt;/code&gt;: Executed after a new commit has been created. Useful for things like notifications.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post-checkout&lt;/code&gt;: Run after any kind of checkout operation, like changing branches. I use this hook in Ruby projects to determine if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt; has
changed, and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle install&lt;/code&gt; if that is the case.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;using-an-external-diff-viewer-kaleidoscope&quot;&gt;Using an external diff viewer (Kaleidoscope)&lt;/h3&gt;

&lt;p&gt;The built-in diff viewer is great most of the time, but sometimes you want to diff non-text files, or simply need a better visualization of what’s going on.&lt;/p&gt;

&lt;p&gt;For this reason, Git allows you to specify external diff viewers. I use the excellent &lt;a href=&quot;http://www.kaleidoscopeapp.com/&quot; title=&quot;Kaleidoscope - File comparison for the Mac&quot;&gt;Kaleidoscope&lt;/a&gt; (OS X only, sorry), which can not only diff text files, but also images. Other options include FileMerge.app, which is included with Apple’s Developer Tools.&lt;/p&gt;

&lt;p&gt;Setting up an external diff viewer usually involves installing some kind of command line app or script. In Kaleidoscope’s case, all you need to do is follow the instructions under &lt;strong&gt;Kaleidoskope&lt;/strong&gt;-&amp;gt;Integration to install the command line tool, and add the relevant lines to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitconfig&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now all I need to do is call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git difftool&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;difftool&lt;/code&gt; takes all the same options as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt;), and Git will invoke Kaleidoscope for me.&lt;/p&gt;

&lt;h3 id=&quot;git-template&quot;&gt;Git template&lt;/h3&gt;

&lt;p&gt;When Git creates a new repository, it uses a template to populate certain files and directories. Assuming your Git is installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local&lt;/code&gt;, you’ll find this template under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/share/git-core/templates&lt;/code&gt;. This is mostly useful to install your custom default hooks, so you don’t have to remember adding them when setting up a new repository.&lt;/p&gt;

&lt;p&gt;If you’ve changed the template after creating a repository, you can simply run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt; inside that repository again, and it will pick up the new template.&lt;/p&gt;

&lt;h1 id=&quot;external-apps&quot;&gt;External Apps&lt;/h1&gt;

&lt;p&gt;There are a few GUI applications that make your life with Git a bit easier, especially when it comes to stuff like history visualization. Here are a few of them.&lt;/p&gt;

&lt;h3 id=&quot;gitx&quot;&gt;GitX&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://gitx.frim.nl/&quot; title=&quot;GitX&quot;&gt;GitX&lt;/a&gt; is my favorite GUI for examining a repository’s history. It shows you all the diffs in a commit, you can search commits, and it even includes some nice functions to create new commits from within GitX, making it a good tool for people who prefer GUIs over the command line. GitX is open source and available on GitHub.&lt;/p&gt;

&lt;p&gt;However, the official version is a bit outdated, so get &lt;a href=&quot;https://github.com/brotherbard/gitx&quot; title=&quot;Brotherbard's GitX fork&quot;&gt;Brotherbard’s improved GitX fork&lt;/a&gt; instead, which offers a few more features and improvements over the original.&lt;/p&gt;

&lt;h3 id=&quot;gitbox&quot;&gt;&lt;a href=&quot;http://www.gitboxapp.com/&quot; title=&quot;Gitbox - The missing version control on a Mac&quot;&gt;Gitbox&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.gitboxapp.com/&quot; title=&quot;Gitbox - The missing version control on a Mac&quot;&gt;Gitbox&lt;/a&gt; (&lt;a href=&quot;http://j.mp/gqjO2m&quot; title=&quot;Gitbox on the Mac App Store (Affiliate link, proceeds go towards Cocoaheads Austria)&quot;&gt;Also available in the Mac App Store&lt;/a&gt;, affiliate link, proceeds go towards Cocoaheads Austria) is another Mac GUI and offers more features than GitX. However, I haven’t used it much, and thus can’t really say much about it. Free for up to 3 repositories, and $39 for full version, so it won’t hurt you to try it out.&lt;/p&gt;

&lt;h3 id=&quot;tower&quot;&gt;&lt;a href=&quot;http://www.git-tower.com/&quot; title=&quot;Tower - The most powerful Git client for Mac&quot;&gt;Tower&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.git-tower.com/&quot; title=&quot;Tower - The most powerful Git client for Mac&quot;&gt;Tower&lt;/a&gt; is a much more powerful than GitX and Gitbox, but is also more complex. If you really don’t like the command line, this might be the client for you. €49, 30 day trial available.&lt;/p&gt;

&lt;h3 id=&quot;ios-apps&quot;&gt;iOS Apps&lt;/h3&gt;

&lt;p&gt;There are also a few apps available for the iPhone and the iPad, but with the exception of Cardff git, they are all geared towards viewing your GitHub account and repositories.&lt;/p&gt;

&lt;p&gt;(Note: The App Store links are affiliate links, proceeds will go towards Cocoaheads Austria)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://j.mp/hbkv7U&quot; title=&quot;By buying this app you'll support Cocoaheads Austria. This will not increase the price of course. Thank you!&quot;&gt;iOctocat&lt;/a&gt; (€3.99, for iPhone, &lt;a href=&quot;https://github.com/dbloete/ioctocat&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;

    &lt;p&gt;A full-blown GitHub companion for your iPhone. Allows you to view feeds, repositories, commits, and user profiles. Can also examine, open, edit or close issues.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://j.mp/i4t3UL&quot; title=&quot;By buying this app you'll support Cocoaheads Austria. This will not increase the price of course. Thank you!&quot;&gt;Cardff Git 1.7&lt;/a&gt; (€0.79, for iPhone)&lt;/p&gt;

    &lt;p&gt;A small cheat sheet app that acts as a handy reference for most Git commands.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://j.mp/dZpJx8&quot; title=&quot;By buying this app you'll support Cocoaheads Austria. This will not increase the price of course. Thank you!&quot;&gt;GitHub Viewer&lt;/a&gt; (€0.79, for iPad)&lt;/p&gt;

    &lt;p&gt;Allows you to view your GitHub repositories, histories, as well as users on GitHub.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://j.mp/e3KaeT&quot; title=&quot;By buying this app you'll support Cocoaheads Austria. This will not increase the price of course. Thank you!&quot;&gt;GitHub Viewer Light&lt;/a&gt; (for iPad)&lt;/p&gt;

    &lt;p&gt;Same as GitHub Viewer, but without the ability to view private repositories.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://j.mp/fQDiZA&quot; title=&quot;By buying this app you'll support Cocoaheads Austria. This will not increase the price of course. Thank you!&quot;&gt;githood&lt;/a&gt; (€0.79, for iPhone)&lt;/p&gt;

    &lt;p&gt;Allows you to track your GitHub repositories, including diffs and feeds.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;stacked-git-stgit&quot;&gt;Stacked Git (stGit)&lt;/h3&gt;

&lt;p&gt;Unlike the other programs, &lt;a href=&quot;http://www.procode.org/stgit/&quot; title=&quot;Stacked Git&quot;&gt;Stacked Git&lt;/a&gt; is not a GUI application. It is a command line app that enhances Git by allowing you to manage a stack of patches on top of your repository. All these patches are stored as ordinary Git commits, but StGit helps you managing these patches.&lt;/p&gt;

&lt;p&gt;I used to use this program quite a lot, but it has since been superseded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;revisions&quot;&gt;Revisions&lt;/h1&gt;

&lt;p&gt;Most Git commands expect some kind of &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html&quot; title=&quot;gitrevisions(7) Manual Page&quot;&gt;revision&lt;/a&gt;. Usually you pass in a branch name or a SHA1 of a specific commit, but Git revisions are much more powerful than that.&lt;/p&gt;

&lt;p&gt;First, there is a special revision called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; (also known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt;). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; is whatever point your working directory currently is at, usually the tip of a branch.&lt;/p&gt;

&lt;p&gt;Second, you can easily reach older commits given a starting ref without having to know their SHA1. Let’s say you want to specify the commit that came before the current one (also called “parent”): Simply type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head^&lt;/code&gt;. The great-grandfather? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head^^^&lt;/code&gt;. However, the farther back you go in history, the more cumbersome it gets. So Git also offers an alternate syntax for this: The great-grandfather can also be specified using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head~3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Want to reach the commit whose commit message matches a certain string? Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:/really awesome commit&lt;/code&gt; to find that really awesome commit.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch@{yesterday}&lt;/code&gt; will give you the revision that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch&lt;/code&gt; was at yesterday, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch@{2 days 3 hours 4 seconds ago}&lt;/code&gt; is the branch, well, 2 days, 3 hours and 4 seconds ago.&lt;/p&gt;

&lt;p&gt;I’ve only scratched the surface of what’s possible, so make sure you read the man page.&lt;/p&gt;

&lt;h1 id=&quot;commands&quot;&gt;Commands&lt;/h1&gt;

&lt;p&gt;Here are a few commands that you may not know yet, or that offer options you haven’t been aware of so far.&lt;/p&gt;

&lt;h3 id=&quot;git-stash1&quot;&gt;git-stash(1)&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash&lt;/code&gt; is something that can be incredibly handy. What it does is very simple: If you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash save&lt;/code&gt;, it will take all the changes you have in your working directory and the index, and save them away, leaving you with a clean working directory. Once you’ve done what you wanted to do, you can restore your changes by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash pop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But it gets better: since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash&lt;/code&gt; saves your changes in a commit, you can stash more than once, and you’ll get a nice list of commits with your stashed changes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash&lt;/code&gt; will also keep track of what branch you stashed your changes on, so you’ll know later on what stashed change exactly you want to restore.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash list&lt;/code&gt; will list all the stashes you’ve saved away, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash apply&lt;/code&gt; will apply the topmost stashed commit onto your working directory, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash pop&lt;/code&gt; will also remove the stashed commit in addition to applying it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash clear&lt;/code&gt; throws away all your stashes, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash drop&lt;/code&gt; allows you to remove a single stash.&lt;/p&gt;

&lt;h3 id=&quot;git-rebase1&quot;&gt;git-rebase(1)&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; can be a very tricky command, although its purpose is very simple: Given a range of commits as well as a starting point, it will port the given commits onto that starting point, preserving the commits themselves, but also allowing you to keep a linear history (that is, no merge commit).&lt;/p&gt;

&lt;p&gt;Most of the time you’ll give it just one ref: The branch you’ll want your current branch to rebase onto. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; then figures out where those two branches diverged, and use that as the beginning of the commit range. If you pass it a second argument, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; will first switch to that branch before porting your commits.&lt;/p&gt;

&lt;p&gt;It also has one very useful flag: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--interactive&lt;/code&gt;. If you pass this flag, Git will launch your favorite editor with a list of all the commits it is going to rebase. All commits are prefixed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pick&lt;/code&gt; by default, but you can either drop commits entirely (just delete their line), reorder them to your liking, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edit&lt;/code&gt; if you’d like to edit or amend the commit (note that this also allows you to split commits), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reword&lt;/code&gt; if you’d just like to change the commit message, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt; if you want to squash the commit with the previous one. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup&lt;/code&gt; will reuse the previous commit’s message, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squash&lt;/code&gt; allows you to edit the new commit’s message.&lt;/p&gt;

&lt;p&gt;The interactive mode is very useful when you’re working on some idea you’ve had, make a commit, and later on realize that it isn’t quite working out that way. You commit a fix, but the commit it fixes is already buried in other commits, so you can’t simply amend. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase --interactive&lt;/code&gt; allows you squash those two commits together and make it look like you never made the mistake in the first place.&lt;/p&gt;

&lt;h3 id=&quot;git-push1&quot;&gt;git-push(1)&lt;/h3&gt;

&lt;p&gt;This is a command that you’re probably using often already, but it gained a few more useful options in recent versions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--set-upstream&lt;/code&gt;: When doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push &amp;lt;repo&amp;gt; local-branch:remote-branch&lt;/code&gt;, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt; to tell Git to set up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote-branch&lt;/code&gt; as the default upstream branch, so you’ll only need to do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; in future.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--delete&lt;/code&gt;: Instead of pushing the specified refs, it will instead delete them from the remote repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;git-reflog1&quot;&gt;git-reflog(1)&lt;/h3&gt;

&lt;p&gt;Whenever an operation changes the tip of a branch, the Reflog mechanism records the old and new locations. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; allows you to access and manage this information.&lt;/p&gt;

&lt;p&gt;This is very useful and potentially life saving after any command that (seemingly) changes the history of your repository, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git filter-branch&lt;/code&gt;. While these commands do indeed change commits, the old commits aren’t deleted, they are merely unreachable by normal means (This is also the reason why Git will occasionally run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git gc&lt;/code&gt; on your repo). However, using the Reflog mechanism you can find out the SHA1’s of these commits, and restore them if you need to.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; lists all the recorded reflog information, and you can then specify any point in the reflog using the syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head@{0}&lt;/code&gt; (where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; is any kind of ref, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; to specify the very first reflog entry). For example, if you just did a rebase, but decided that you messed up somehow, you can restore your branch to its state before the rebase by using this command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset head@{1}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;getting-diffstats&quot;&gt;Getting diffstats&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff --stat
git log --stat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not much to add, really.&lt;/p&gt;

&lt;h1 id=&quot;scripts&quot;&gt;Scripts&lt;/h1&gt;

&lt;p&gt;These are a few of my custom scripts that I use in my Git workflows. They have usually been copied from somewhere else, and then modified for my needs. Find their current versions in my &lt;a href=&quot;https://github.com/cypher/dotfiles&quot; title=&quot;cypher/dotfiles on GitHub&quot;&gt;dotfiles&lt;/a&gt; repo.&lt;/p&gt;

&lt;p&gt;One trick that not too many people are probably aware of: If you have a script named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-foo&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PATH&lt;/code&gt;, and you call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git foo&lt;/code&gt;, Git will actually automatically call you script for you. This way you can easily extend Git with seemingly built-in commands, and you don’t have to worry about any aliases like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;git-up-git-reup&quot;&gt;git-up, git-reup&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; will only tell you that there were new commits, and display a diffstat to show you which files changed. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git up&lt;/code&gt; does a bit more: It will not only pull new commits, but also show you a shortlog of all the new commits, giving you a quick overview of all the new commits.&lt;/p&gt;

&lt;p&gt;However, when invoked as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reup&lt;/code&gt;, it essentially does the same thing, with one difference: Instead of performing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt;, it will do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase&lt;/code&gt; (as well as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash save&lt;/code&gt; beforehand and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git stash pop&lt;/code&gt; afterwards if you have a dirty working directory), thus preserving a linear history. And in addition to the log, you’ll also get a diffstat to see all the changes.&lt;/p&gt;

&lt;h3 id=&quot;git-new-workdir&quot;&gt;git-new-workdir&lt;/h3&gt;

&lt;p&gt;Sometimes you want two branches of your repository checked out at the same. One solution to this is to simply create a second, local clone of your repo, and check out the other branch there. But now you have to keep that second repository in sync with the original one, since commits to the one won’t automagically migrate to the other.&lt;/p&gt;

&lt;p&gt;This is where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git new-workdir&lt;/code&gt; comes in: You pass it the path to the original repository, along with the path where you want the second repository to reside, optionally telling it which branch you want to use for your second repo. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git new-workdir&lt;/code&gt; will then set up a second repository in such a way that it is effectively a second checkout, and you won’t have to push or pull to keep them in sync.&lt;/p&gt;

&lt;h3 id=&quot;git-wtf&quot;&gt;git-wtf&lt;/h3&gt;

&lt;p&gt;This is a very handy script: Run it on any branch that has a remote tracking branch, and it will tell you wether they are in sync, or which commits (on each branch) are missing from the other, so you can quickly figure out the state of your local and remote branch.&lt;/p&gt;

&lt;p&gt;Example output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Local branch: master
[ ] NOT in sync with remote (you should push)
    - Add vim-endwise [af43b93]
    - Update vim plugins [a926c01]
    - Add TComment plugin for Vim [035d3b9]
    - Add matchit plugin for Vim [7b76c04]
    - Add vim-markdown plugin [a6e7c19]
    ... and 3 more (use -A to see all).
Remote branch: origin/master (git@github.com:cypher/dotfiles.git)
[x] in sync with local

NOTE: working directory contains modified files.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;aliases&quot;&gt;Aliases&lt;/h1&gt;

&lt;p&gt;Here are some of the aliases that I use that aren’t simply abbreviations of my common git operations.&lt;/p&gt;

&lt;h3 id=&quot;git-l&quot;&gt;git l&lt;/h3&gt;

&lt;p&gt;Shows a one-line history of the current branch, along with any ref names of commits.&lt;/p&gt;

&lt;h3 id=&quot;git-lg&quot;&gt;git lg&lt;/h3&gt;

&lt;p&gt;Similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git l&lt;/code&gt;, but uses the graph format to visualize branches &amp;amp; merges.&lt;/p&gt;

&lt;h3 id=&quot;git-ls-ignored&quot;&gt;git ls-ignored&lt;/h3&gt;

&lt;p&gt;Lists all files that Git ignores right now due to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;git-amend&quot;&gt;git amend&lt;/h3&gt;

&lt;p&gt;Quickly amend the previous commit with the currently staged changes, without editing the commit message.&lt;/p&gt;

&lt;h3 id=&quot;git-ca&quot;&gt;git ca&lt;/h3&gt;

&lt;p&gt;Same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git amend&lt;/code&gt;, but allows you to edit the commit message.&lt;/p&gt;

&lt;h3 id=&quot;git-wd-git-wds&quot;&gt;git wd, git wds&lt;/h3&gt;

&lt;p&gt;Shows a diff that not only highlights the changed lines, but also the actual words and characters in each line that have changed. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git wds&lt;/code&gt; does the same for staged changes.&lt;/p&gt;

&lt;h1 id=&quot;github&quot;&gt;GitHub&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com&quot; title=&quot;GitHub&quot;&gt;GitHub&lt;/a&gt; specific tools and workflows I use.&lt;/p&gt;

&lt;h3 id=&quot;github-gem&quot;&gt;github gem&lt;/h3&gt;

&lt;p&gt;Install via RubyGems as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem install github
# Use sudo if necessary
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/defunkt/github-gem&quot; title=&quot;defunkt/github-gem&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt;&lt;/a&gt; is a command line tool that helps you interact with GitHub without leaving the command line, like creating a new repository, fetching forks of a repo, forking, examining the network of a repository, generating pull requests, and so on.&lt;/p&gt;

&lt;p&gt;It installs itself as both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh&lt;/code&gt;, and passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt; will give you all the available commands.&lt;/p&gt;

&lt;p&gt;Note: If you’re using Ruby 1.9, the installation process may fail with an error message like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-hyphen requires Ruby version &amp;lt; 1.9&lt;/code&gt;. If you pass the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--force&lt;/code&gt; flag to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gem&lt;/code&gt;, it will install it anyway, and so far I haven’t had any problems.&lt;/p&gt;

&lt;h3 id=&quot;git-pulls&quot;&gt;git-pulls&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/schacon/git-pulls&quot; title=&quot;schacon/git-pulls&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pulls&lt;/code&gt;&lt;/a&gt; is a new tool that helps you managing and merging pull requests.&lt;/p&gt;

&lt;p&gt;Install it via RubyGems:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem install git-pulls
# Use sudo if necessary
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is then available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pulls &amp;lt;subcommand&amp;gt;&lt;/code&gt;. If you leave out the subcommand, you’ll get a short overview of all available commands. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; will list all open pull requests, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show&lt;/code&gt; will show you a specific pull request. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge&lt;/code&gt; will make you a cup of coffee (actually, it’ll merge the given pull request, but you probably guessed that already, didn’t you?)&lt;/p&gt;

&lt;p&gt;It’s still under active development, so make sure to always run the latest version (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gem update git-pulls&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;pull-requests&quot;&gt;Pull Requests&lt;/h3&gt;

&lt;p&gt;If someone forks your repo on GitHub, and pushes their commits to their fork, they will probably want you to eventually merge their changes back.&lt;/p&gt;

&lt;p&gt;GitHub supports this workflow using a mechanism called &lt;a href=&quot;https://github.com/features/projects/codereview&quot; title=&quot;GitHub Features: Code Reviews&quot;&gt;Pull Requests&lt;/a&gt;. Whenever you want someone else to merge one or more commits into their repository, you can issue a Pull Request. In addition to the commits, the pull request also contains a description of all the commits contained in the request. After you’ve created one, other people can then comment on the request itself, view all the changes it introduces, and even comment on specific lines. The issuer can also amend his pull request with additional commits to address issues others have found. This makes pull requests an excellent code review tool.&lt;/p&gt;
</description>
        <pubDate>Fri, 18 Feb 2011 00:00:00 +0100</pubDate>
        <link>https://nuclearsquid.com/writings/git-tricks-tips-workflows/</link>
        <guid isPermaLink="true">https://nuclearsquid.com/writings/git-tricks-tips-workflows/</guid>
        
        
        <category>git</category>
        
      </item>
    
  </channel>
</rss>

