<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>git on CodeGoalie</title><link>https://codegoalie.com/categories/git/</link><description>Recent content in git on CodeGoalie</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 04 Jan 2023 14:35:12 -0500</lastBuildDate><atom:link href="https://codegoalie.com/categories/git/index.xml" rel="self" type="application/rss+xml"/><item><title>One-liner to copy a Github PR link from the terminal</title><link>https://codegoalie.com/posts/copy-pr-link/</link><pubDate>Wed, 04 Jan 2023 14:35:12 -0500</pubDate><guid>https://codegoalie.com/posts/copy-pr-link/</guid><description>&lt;p>Here&amp;rsquo;s a super quick one-liner to copy the current branch&amp;rsquo;s PR URL to your
clipboard (for posting into Slack, tickets, etc.)&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ gh pr view --json url --jq .url | &amp;lt;pbcopy | xclip -sel c&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Remember to replace the copy command with your platform&amp;rsquo;s specific command.&lt;/p>
&lt;p>This would also make a good shell alias.&lt;/p>
&lt;p>Also, also, I might try setting up &lt;a href="https://github.com/Slackadays/Clipboard">Clipboard&lt;/a> for multi-platform goodness.&lt;/p>
&lt;p>Happy PR-ing!&lt;/p>
&lt;p>&amp;ndash; Chris&lt;/p></description></item><item><title>Commit Before Code</title><link>https://codegoalie.com/posts/commit-before-code/</link><pubDate>Fri, 26 Jun 2020 06:43:29 -0400</pubDate><guid>https://codegoalie.com/posts/commit-before-code/</guid><description>&lt;p>I propose a case for writing all of your commit messages for a feature, bug,
pull request &lt;em>before&lt;/em> writing a single line of code and afterward not adding
any additional commits to your branch. Plan and execute. Give clarity and focus
to your reviewers. Here&amp;rsquo;s how.&lt;/p>
&lt;p>This is an idea that&amp;rsquo;s been floating around in my head for a while now:
pre-planning commits in your branches. In fact, I checked my older posts
because I thought there might be a pretty good chance I had written this post
already. There wasn&amp;rsquo;t. So, here it is.&lt;/p>
&lt;h2 id="what-am-i-talking-about">What am I talking about?&lt;/h2>
&lt;p>Making all your commits to complete your task &lt;em>before&lt;/em> you begin coding.
Literally using &lt;code>--allow-empty&lt;/code> to outline all the tasks your branch needs to
do before you write one line of code. Every commit after that of code changes
are all &lt;code>fixup&lt;/code> commits to one of the original commits. No new commits allowed.&lt;/p>
&lt;h2 id="why-would-anyone-do-that">Why would anyone do that?&lt;/h2>
&lt;p>I find the exercise of planning my attack in the form of concrete commits
beneficial for &lt;strong>clarity&lt;/strong> and &lt;strong>focus&lt;/strong>.&lt;/p>
&lt;p>First, I can think abstractly about the work to be done. I don&amp;rsquo;t know which
lines of code will change or even what they will change into, but rather, I can
focus solely on what those changes need to achieve.&lt;/p>
&lt;p>I can think at a much higher level and coordinate the expected changes together
without getting bogged down by the intricacies or specific implementation
details. I don&amp;rsquo;t need to think about error handling, variable naming, design
patterns, code smells, testability, etc. (unless any of those are core to the
rationale of the branch). It&amp;rsquo;s almost a pure-er way of processing the task at
hand. I focus only on what are the smallest set of steps to reach the goal.&lt;/p>
&lt;p>Secondly, and often more importantly, I force myself to remain focused on the
task at hand. If I make a change that doesn&amp;rsquo;t fit into any of the predetermined
commits, there&amp;rsquo;s a very good chance that the change doesn&amp;rsquo;t belong in this
branch and should be made elsewhere.&lt;/p>
&lt;p>Most often these are housekeeping tasks; small improvements to the code that I
happen to notice while doing something unrelated. Sometimes these are areas
that don&amp;rsquo;t adhere to newly adopted best practices. Or, improvements in
readability. These aren&amp;rsquo;t things that are critical, but help keep code quality
up over time. I&amp;rsquo;ll get into what to do with these kinds of changes later.&lt;/p>
&lt;h2 id="ok-but-how-can-i-do-this">Ok, but how can I do this?&lt;/h2>
&lt;p>Let&amp;rsquo;s take an example and build out our branch of empty commits. Imagine we&amp;rsquo;re
working on an app to track vacations. We have an entity that holds our check-in
and check-out dates. What we want now is to display the number of days and
nights of the stay. For example, a stay from July 14th to 20th is 7 days/6
nights.&lt;/p>
&lt;p>One thing to notice about this new feature is that the numbers are always one
off from each other. We can calculate one and then derive the other.&lt;/p>
&lt;p>I like to write my tests first (in one commit) and then get them to pass in
another. I&amp;rsquo;ll also prefix my test-only commits with &amp;ldquo;Ensure&amp;rdquo;. Using this
pattern, I&amp;rsquo;d want to write test for and then implement the number of days
calculation. Then test and implement displaying to users. Here&amp;rsquo;s the commands to
acheive this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">$ git commit --allow-empty -m &lt;span style="color:#e6db74">&amp;#34;Ensure amount of days can be calculated from trips&amp;#34;&lt;/span>
$ git commit --allow-empty -m &lt;span style="color:#e6db74">&amp;#34;Calculate amount of days from trips&amp;#34;&lt;/span>
$ git commit --allow-empty -m &lt;span style="color:#e6db74">&amp;#34;Ensure users can see days/nights for a trip&amp;#34;&lt;/span>
$ git commit --allow-empty -m &lt;span style="color:#e6db74">&amp;#34;Display days/nights for trips&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then after writing the tests for the calculation, I would create a &lt;code>fixup&lt;/code>
commit to &lt;a href="https://codegoalie.com/2013/04/04/better-pull-requests-with-git-autosquash">autosquash&lt;/a> into the first commit from above:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">$ git commit --fixup HEAD~~~ &lt;span style="color:#75715e"># using a relative commit reference&lt;/span>
&lt;span style="color:#75715e"># or with the sha1 (prefix)&lt;/span>
$ git commit --fixup 06aa143
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Learn more about &lt;a href="https://codegoalie.com/2016/04/06/git-references">git references&lt;/a>.&lt;/p>
&lt;p>When all is said and done (or even before that), you can have git clean things
up for you with:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">$ git rebase master --autosquash
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="what-about-those-small-unrelated-changes">What about those small, unrelated changes?&lt;/h2>
&lt;p>These are changes I, personally, love to make. I believe this is where the
rubber meets the road in software as a craft. The holy trail of the huge
rewrite is often so tempting, but if you can&amp;rsquo;t put new learnings or best
practices into existing code then how can you think that you&amp;rsquo;ll be able to do
it in a brand new system. If you can prove that you are a good enough developer
to make the existing system its best, then you know you are ready to tackle a
rewrite. However, you also won&amp;rsquo;t need to. ;)&lt;/p>
&lt;p>So, what could be the harm of slipping in some minor improvements with your other
work? I&amp;rsquo;m already in here. Let&amp;rsquo;s just fix it really quick. Well, this will get
you into trouble in at least 2 ways.&lt;/p>
&lt;p>First, if the rest of your branch becomes obsolete or a better solution
arrives before you merge, the codebase doesn&amp;rsquo;t get to benefit from your
unmerged, unrelated change. Or worse still, if your merged branch needs to be
reverted, you will also be reverting your unrelated change.&lt;/p>
&lt;p>Secondly, it has a very real chance to hold up your PR during review. There&amp;rsquo;s
no better way to almost guarantee a flame war than think you can squeeze in
a small, quick change. &amp;ldquo;Why is this fix here?&amp;rdquo; &amp;ldquo;If you&amp;rsquo;re fixing this, why
didn&amp;rsquo;t you fix that?&amp;rdquo; &amp;ldquo;You should fix it in this way instead.&amp;rdquo;, etc. Your
2 second &amp;ldquo;improvement&amp;rdquo; will undoubedly attract comments and suggestions like
moths to a flame. The &lt;strong>actual&lt;/strong> point of the PR will be fine, but you&amp;rsquo;ll get
stuck going around and around on your small addiiton.&lt;/p>
&lt;h2 id="if-you-cant-make-these-changes-in-your-current-branch-where-do-they-go">If you can&amp;rsquo;t make these changes in your current branch, where do they go?&lt;/h2>
&lt;p>&lt;strong>TL;DR&lt;/strong> Move them into another branch and open a separate PR.&lt;/p>
&lt;p>There are 2 ways to do this. One uses the stash and one uses commits and cherry
picking. I&amp;rsquo;ll start with stash.&lt;/p>
&lt;p>Use the &lt;a href="https://git-scm.com/docs/git-stash">git-stash&lt;/a> to move changes across branches. The stash is a temporary
holding place for uncommitted changes. You can stash these changes on one branch
and apply them to another. I&amp;rsquo;ll assume you&amp;rsquo;ve committed all changes with fixups
and want to move all uncommitted changes to another branch.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">$ git stash save
$ git checkout master
$ git checkout -b a-good-name-for-changes
$ git stash pop
$ git add .
$ git commit
$ git push
&lt;/code>&lt;/pre>&lt;/div>&lt;p>I always prefer &lt;code>git stash pop&lt;/code> to &lt;code>git stash apply&lt;/code> because the former removes
the stash entry when applying it and keeps your stash clean. Once it&amp;rsquo;s applied
and committed, you no longer need that stash and there&amp;rsquo;s no sense in keeping it
around.&lt;/p>
&lt;p>Now, for the second way. This way is a little less dangerous since you always
have your changes committed, but maybe only by a hair. Here you&amp;rsquo;ll commit to
your working branch. Then create a new branch and cherry pick that commit into
the new branch. This technique also works will if your &amp;ldquo;small&amp;rdquo; fix has multiple
commits.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-sh" data-lang="sh">$ git commit
&lt;span style="color:#f92672">[&lt;/span>commit-before-code e4fe22f&lt;span style="color:#f92672">]&lt;/span> Prefer single quoted strings
&lt;span style="color:#ae81ff">1&lt;/span> file changed, &lt;span style="color:#ae81ff">3&lt;/span> insertions&lt;span style="color:#f92672">(&lt;/span>+&lt;span style="color:#f92672">)&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span> deletions&lt;span style="color:#f92672">(&lt;/span>-&lt;span style="color:#f92672">)&lt;/span>
$ git checkout master
$ git checkout -b string-style-fixes
$ git cherry-pick e4fe22f
$ git push
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>ProTip: &lt;code>cherry-pick&lt;/code> takes any git commit reference. Utilize the branch name
to cherry pick the tip of that branch into your current branch.&lt;/p>
&lt;/blockquote>
&lt;p>The really cool thing about this method is that if your fix branch gets merged
before your feature branch, you can simply rebase on master (which you should be
doing anyway) and git will detect the duplicate changes and automatically remove
the cherry picked commit.&lt;/p>
&lt;hr>
&lt;p>Next time you are starting to work on a new branch, give this method a try and
see if it helps keep you clear on your objective and focused on nailing it.&lt;/p>
&lt;p>Let me know how it works out for you.&lt;/p>
&lt;p>Happy committing!&lt;/p>
&lt;p>— Chris&lt;/p></description></item><item><title>Git References</title><link>https://codegoalie.com/posts/git-refs/</link><pubDate>Wed, 06 Apr 2016 23:04:17 -0400</pubDate><guid>https://codegoalie.com/posts/git-refs/</guid><description>&lt;p>Everyone knows how to checkout a branch, &lt;code>git checkout master&lt;/code>, or how to look
at a specific commit, &lt;code>git show a1c8b6d&lt;/code>. But few know that branches, tags,
and commit SHAs are typically interchangeable in these and many other &lt;code>git&lt;/code>
commands. Plus there is a whole set of modifiers to reference commits near to
specific commits. In this post, we&amp;rsquo;ll explore all these techniques to become
expert &lt;code>git&lt;/code> referencers.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;h1 id="references">References&lt;/h1>
&lt;p>Below we will explore the different ways we can express a commit in &lt;code>git&lt;/code>. While
each technique has its own strengths and weaknesses, being able to wield a lot
of &lt;code>git&lt;/code>&amp;rsquo;s power and saving a lot of time comes from using these references
interchangeably.&lt;/p>
&lt;h2 id="sha1s">SHA1s&lt;/h2>
&lt;p>This first and most recognizable way to reference a commit is by its SHA1. This
is the full or part of the long random looking string of letters and numbers.
These are generated based on the contents of the commit, including current state
of the repo&amp;rsquo;s files, commit message, author and committer, and timestamp. If any
of those items change, a new SHA1 will be generated. Here are some examples of
&lt;code>git&lt;/code> commands using the SHA1.&lt;/p>
&lt;pre>&lt;code>git show abc123
git cherry-pick 321bca
git reset bbbaa4
&lt;/code>&lt;/pre>&lt;h2 id="branch-names">Branch Names&lt;/h2>
&lt;p>Branch names are also something that are a big part of a &lt;code>git&lt;/code> workflow. Under
the hood, branch names are just aliases for commit SHA1s. Literally, you can see
the branch names in the &lt;code>.git/refs/heads&lt;/code> directory of your repo. Each file
there contains one line which has the SHA1 of the commit it references. Here are
some common usages of branch names:&lt;/p>
&lt;pre>&lt;code>git checkout master
git rebase stable
git merge features/new-hottness
git cherry-pick bugs/broken-email-form
&lt;/code>&lt;/pre>&lt;p>An important aspect of branch names is the commit they reference can change. For
example, when you create a new commit the branch which you are currently on
automatically gets updated to the new SHA1.&lt;/p>
&lt;h2 id="tags">Tags&lt;/h2>
&lt;p>Tags are very similar to branch names in that they are also friendlier aliases
for commit SHA1s. However, unlike branches, tags cannot be changed once created.
This makes them ideal for marking fixed, important commits in the history of
your code base. Releases and versions are a good usage for tags. Here are some
example commands using tags:&lt;/p>
&lt;pre>&lt;code>git tag v1.0.0
git checkout -b 1.1-backport v1.1.0
git show v0.9.0
&lt;/code>&lt;/pre>&lt;h2 id="head">HEAD&lt;/h2>
&lt;p>The &lt;code>HEAD&lt;/code> commit is the current tip of the branch you are on. Similar to the
&lt;code>pwd&lt;/code> program, &lt;code>HEAD&lt;/code> tells you where you are. On its own, the useful command is
&lt;code>show&lt;/code> which will show you the details of the last commit you made.&lt;/p>
&lt;h1 id="modifiers">Modifiers&lt;/h1>
&lt;p>&lt;code>git&lt;/code> also allows you to specify commits by their relation to other commits. In
the &lt;code>git&lt;/code> data structure the only explicit relationship between commits is
child-parent. That is, the child commit knows its parent, but the parent does
not know its child/children. Many of the commands which show or span multiple
commits, such as &lt;code>log&lt;/code> or &lt;code>diff&lt;/code>, actually traverse the git tree to aggregate
their output.&lt;/p>
&lt;h2 id="first-parent">First Parent&lt;/h2>
&lt;p>The &lt;code>~&lt;/code> modifier follows a references first parent. For example, &lt;code>HEAD~&lt;/code>
references the first parent of the current commit. The first parent modifier can
be repeated: &lt;code>HEAD~~&lt;/code> references the first parent of the first parent of the
current commit. Also, a number can be specified for many generations: &lt;code>HEAD~5&lt;/code>
follows ancestors back 5 generations. Here are some other uses of the first
parent modifier:&lt;/p>
&lt;pre>&lt;code>// Move the second to last commit into the current branch
git cherry-pick bugs/broken-email-form~
// Modify some of the last 5 commits on your branch
git rebase HEAD~6
// Mark your current changes to fixup into two commits ago
git commit -a --fixup HEAD~
&lt;/code>&lt;/pre>&lt;h2 id="other-parents">Other Parents&lt;/h2>
&lt;p>Through merges, a commit can have multiple parents. The last modifier of the day
specifies any parent of a commit. The caret, &lt;code>^&lt;/code>, modifies the reference to
follow its first parent; the same as &amp;lsquo;~&amp;rsquo;. However, specifying a number along
with the caret follows subsequent parent commits. For example, reference the
last commit of a branch before it was merged into the current branch with
&lt;code>HEAD^2&lt;/code>.&lt;/p>
&lt;h1 id="bringing-it-all-together">Bringing it all together&lt;/h1>
&lt;p>Any of the above references can be combined with any number of modifiers to
express the exact commit succinctly. Here are some examples:&lt;/p>
&lt;pre>&lt;code>// See the 3rd to last commit from the last branch merged to the stable branch
git show stable^2~~~
// Pull second to last commit from version 2 into your current branch
git cherry-pick v2.0.0~
// Create a new branch 2 commits back from a known SHA1
git checkout -b branch-from-history abcd122~~
&lt;/code>&lt;/pre>&lt;p>The above examples might seem extremely specific, but knowing and using these
techniques can turn wasted time digging through git logs or copy and pasting
SHA1s into a quick one-liner. Impress your friends and co-workers, save your own
time, and begin thinking of your &lt;code>git&lt;/code> history relatively.&lt;/p>
&lt;p>Happy referencing!!&lt;/p>
&lt;p>&amp;ndash; Chris&lt;/p></description></item><item><title>Delete multiple branches with git</title><link>https://codegoalie.com/posts/2014-06-25-delete-multiple-branches-with-git/</link><pubDate>Wed, 25 Jun 2014 00:00:00 +0000</pubDate><guid>https://codegoalie.com/posts/2014-06-25-delete-multiple-branches-with-git/</guid><description>&lt;p>When working on projects with multiple developers following a feature branching
workflow, you can end up with a lot of branch laying around. I&amp;rsquo;ve been trying to
optimize my branch cleanup workflow for a while now and had a big breakthrough
recently.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>&lt;strong>UPDATE:&lt;/strong> I now use a &lt;a href="https://github.com/pengwynn/dotfiles/blob/master/bin/git-sweep">shell
script&lt;/a>
which has the meat of the git-sweep functionality. Thanks to @pengwynn
for letting me steal that.&lt;/p>
&lt;p>Before we get to that, I must mention &lt;a href="http://lab.arc90.com/2012/04/03/git-sweep/">git-sweep&lt;/a>.
It has been revolutionary to keeping branches (both locally and remote) clean.
If you care at all about the output of &lt;code>git branch&lt;/code>, install that now.&lt;/p>
&lt;p>However, there&amp;rsquo;s another simpler trick I just recently discovered. Deleting
multiple local branches with one command.&lt;/p>
&lt;pre>&lt;code>$ git branch -D old-branch-1 old-branch-2
&lt;/code>&lt;/pre>
&lt;p>That&amp;rsquo;s it! Simply pass as many branches into &lt;code>branch -D&lt;/code> as you want and &lt;code>git&lt;/code>
will gladly delete them all.&lt;/p>
&lt;h3 id="but-why-do-you-need-this">But why do you need this?&lt;/h3>
&lt;p>I just said that &lt;code>git-sweep&lt;/code> cleans up local and remote branches after they are
merged into &lt;code>master&lt;/code>. So, why would we ever need to delete local branches? For
one, you might not merge branches into master, but still want to delete them.
But more likely, you&amp;rsquo;ll need to do this after pulling down a colleague&amp;rsquo;s branch
to review. Once you give them the green light, it&amp;rsquo;s best practice for them to
rebase onto &lt;code>master&lt;/code> (interactively to prevent accidentally merging &lt;code>!fixup&lt;/code>
commits). However, you will have one state of the branch locally, but they&amp;rsquo;ve
merged a different, rebased state. This is just enough of a change to fool
&lt;code>git-sweep&lt;/code>, and &lt;code>git&lt;/code> herself, into missing the fact that these branches are
the same. Luckily, there is a quick way to identify and remove those branches
too.&lt;/p>
&lt;p>Handily, &lt;code>git-branch&lt;/code> has a super verbose mode which can be shown with the
&amp;ldquo;double v&amp;rdquo; flag (&lt;code>-vv&lt;/code>). This displays the branch name, HEAD commit, remote
tracking branch, and HEAD commit message.&lt;/p>
&lt;pre>&lt;code>$ git branch -vv
* gh-pages 123456 [origin/gh-pages] Show new features on the project website
master 654321 [origin/master] Merge features/super-new-feature into master
&lt;/code>&lt;/pre>
&lt;p>Additionally, super verbose mode will also show us when a remote tracking branch
disappears (is deleted). Immediately following the tracking branch name, we&amp;rsquo;ll
notice a &amp;ldquo;gone&amp;rdquo;.&lt;/p>
&lt;pre>&lt;code>$ git branch -vv
* master 654321 [origin/master] Merge features/super-new-feature into master
old-feature 523621 [origin/old-feature: gone] Users can see the brand new feature
&lt;/code>&lt;/pre>
&lt;p>I like to &lt;code>grep&lt;/code> for that and filter out the branches which I don&amp;rsquo;t want to
delete. Basically, my whole cleanup procedure goes like this:&lt;/p>
&lt;pre>&lt;code>$ git branch -vv | grep gone]
old-feature-1 523621 [origin/old-feature-1: gone] Link to the new account page
old-feature-2 856956 [origin/old-feature-2: gone] Toggle turtle visibility with feature flag
$ git branch -D old-feature-1 old-feature-2
Deleted branch old-feature-1 (was 523621).
Deleted branch old-feature-2 (was 856956).
&lt;/code>&lt;/pre>
&lt;p>And there you have it, removing multiple branches in git with a bonus of
finding branches who&amp;rsquo;ve lost their remote tracks.&lt;/p>
&lt;p>Happy branching!!&lt;/p>
&lt;p>&amp;ndash; Chris&lt;/p></description></item><item><title>Commit Message Starters</title><link>https://codegoalie.com/posts/2013-05-14-commit-message-starters/</link><pubDate>Tue, 14 May 2013 00:00:00 +0000</pubDate><guid>https://codegoalie.com/posts/2013-05-14-commit-message-starters/</guid><description>&lt;p>As I&amp;rsquo;ve been working in git and crafting my commits with rebase
working toward creating pull requests which are easy to read,
review, and comment, I&amp;rsquo;ve been noticing myself fall into
habits of naming commit messages similarly which contain code to
acheive similar ends. Further, when I struggle to find the correct
words for a commit message, it&amp;rsquo;s often easier to being with
a familiar word to get things flowing.&lt;/p>
&lt;p>{% img right /images/readthesource.jpg 460 276 Read the source %}
Over the past few months, I&amp;rsquo;ve also had the pleasure of working
with some great developers. As such, I&amp;rsquo;ve been afforded the
opportunity to review a lot of their code. If there is one thing I recommend
to all developers, from novice to expert, it&amp;rsquo;s &lt;em>&lt;strong>read code&lt;/strong>&lt;/em>.
Your own, your friend&amp;rsquo;s, strangers, projects you admire, anything you can get
your hands on.
Not only will it enlighten you to how others write code, new coding patterns
and syntax, but it will empower you to be able to figure out how the code you
use works and how to fix it.&lt;/p>
&lt;p>As a quick aside, I was able recently to dig into the Ruby source code, even
into the C, to discover exaclty what was happening with Range bracket
operator access on an empty Array. It felt great to be able to see how Ruby
herself was implemented and know exactly why my code worked; to go beyond &amp;ldquo;well,
it worked in irb so it must be correct.&amp;rdquo;&lt;/p>
&lt;p>The great thing about reviewing pull requests is that I am able to open
discussions with the authors and inquire as to why they made certain decisions
and what their motiviations were for writing certain code. Also, it gave me a
chance to see code which was not polished and final. Thereby, recognizing
anti-patterns and less than best practices.&lt;/p>
&lt;p>Coming back to the topic of this post. These anti-patterns and less than best-
practices extend to commit messages as well. Below I&amp;rsquo;ve listed some of the dos
and don&amp;rsquo;ts which I have started to use in my everyday committing.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;h2 id="what-i-like">What I like&lt;/h2>
&lt;p>These words I often use to start commit messages which make some common
changes in the codebase.&lt;/p>
&lt;h3 id="ensure">Ensure&lt;/h3>
&lt;pre>&lt;code>Ensure phone numbers strip extraneous characters
Ensure deactivation resets users' api tokens
&lt;/code>&lt;/pre>
&lt;p>I use &amp;ldquo;Ensure&amp;rdquo; to start a commit which contains tests for my code. These commits
are often the first commits in a pull request, especially if I am using TDD. A
whole commit just for test? Surely, that&amp;rsquo;s overkill? There are two reasons I
like to encapsulate tests into their own commits.&lt;/p>
&lt;p>{% img left /images/ensure.jpg Ensure %} First, this standardization allows
others to know which commits will define
and test the behavior I aim to implement. We all know that tests can be a great
documentation tool and prefixing commit messages which contain &amp;ldquo;Ensure&amp;rdquo; allow
people to find them easier.&lt;/p>
&lt;p>Second, if the tests are in their own commit(s) &lt;em>before&lt;/em> the implementation
commits, it&amp;rsquo;s very easy for a reviewer to simulate the red-green test cycle.
Either through a &lt;code>checkout&lt;/code> or selecting a commit to be &amp;lsquo;editied&amp;rsquo; in an
interactive rebase, the state of the repo &lt;em>after&lt;/em> the tests are written, but
&lt;em>before&lt;/em> the task is implemented can be recreated. Tests are run at that point
and a reviewer can cofirm that the new tests do indeed fail. The rebase is
continued and the tests can be run again. This time they succeed. A review has
very simply been able to confirm that the tests are working correctly.&lt;/p>
&lt;h3 id="boyscout">Boyscout&lt;/h3>
&lt;pre>&lt;code>Boyscout the user model specs
Boyscout line lengths in the sessions controller
&lt;/code>&lt;/pre>
&lt;p>Boyscouting refers to updating the format and/or style of code without changing
the behavior. I picked it up from a presentation about code styles which I now
cannot find to reference here. However, I did find this
&lt;a href="http://www.cimgf.com/zds-code-style-guide/">written reference&lt;/a> online.
The term refers to a famous quote by the founder of the Boyscouts,
Robert Stephenson Smyth Baden-Powell,
&lt;a href="http://www.scouting.org/scoutsource/CubScouts/Parents/About/history.aspx">&amp;ldquo;Try and leave this world a little better than you found
it&amp;rdquo;&lt;/a>.&lt;/p>
&lt;p>Continuing to think of the reviewer when committing, just by looking at the
message, expectations are set that this commit does not change functionality,
only formatting. Review of a change like that is much easier when you know that
nothing is supposed to happen.&lt;/p>
&lt;h3 id="migrate">Migrate&lt;/h3>
&lt;pre>&lt;code>Migrate a unique index for user email addresses
Migrate timestamp columns onto the comments table
&lt;/code>&lt;/pre>
&lt;p>As you might have guessed, I use &amp;ldquo;Migrate&amp;rdquo; to start commit messages which
contain migrations. As a best practice, we like to isolate migrations to their
own commits containing only the migration class definition and the changes to
the schema file. It also can be useful, but not 100% reliable, to quickly see
if a particular set of commits has migrations; say before a deploy or after
pulling down the latest changes. Again, along the theme of setting expectations
for others.&lt;/p>
&lt;h2 id="what-i-avoid">What I avoid&lt;/h2>
&lt;p>These words often start a commit message off on the wrong foot. Being very
generic on their own, they often lead to very generic commit messages.&lt;/p>
&lt;h3 id="fixed">Fixed&lt;/h3>
&lt;pre>&lt;code>Fixed broken specs
Fixed editing a user
&lt;/code>&lt;/pre>
&lt;p>{% img right /images/fixedit.jpg FIXED!!! %}
First off, past tense should be avoided in commit messages. The rule of thumb
is to write a commit message as if you were commanding the code to take an
action. Secondly, commit messages should describe the reason for a change, not
the change itself. If someone would like a know what the changes were, they
need to do no more that a &lt;code>git show&lt;/code> or click in github. However, to reason
why the change was made or what it is attempting to do is much harder to
determine from the code itself. Great commit messages can be the difference
between &lt;code>Fixed broken specs&lt;/code> and &lt;code>Activate users after registration in user specs&lt;/code>.&lt;/p>
&lt;h3 id="added">Added&lt;/h3>
&lt;pre>&lt;code>Added new Order model
Added full_name method to User model
&lt;/code>&lt;/pre>
&lt;p>&amp;ldquo;Added&amp;rdquo; is not strictly a not so best practice, but I see it go awry more often
than I see it used for good. Again, &amp;ldquo;added&amp;rdquo; has a great tendnecy to lean toward
&lt;em>what&lt;/em> happened instead of &lt;em>why&lt;/em> did it happen. I, myself, sometimes write a
commit starting with &amp;ldquo;added&amp;rdquo;. For example, &lt;code>Added jquery javascript library&lt;/code>
at first glance seems perfectly reasonable. I didn&amp;rsquo;t fix anything. I didn&amp;rsquo;t
write a great new feature. I just added jQuery. However, when I find myself
with a commit message like this, I go through the practice of adding &amp;ldquo;in order
to&amp;rdquo; and then trying to finish the commit message. &lt;code>Added jquery javascript library&lt;/code> in order to &lt;code>provide DOM manipulation methods&lt;/code>. Put it
together for &lt;code>Provide DOM manipulation methods with jQuery&lt;/code>. Now, I&amp;rsquo;ve given
some context to why I added jQuery instead of simply restating the code changes
in the commit message.&lt;/p>
&lt;p>That&amp;rsquo;s all I have for now. Please comment below with your commit message best
practices and tendencies. I bet you guys have some great tips too!&lt;/p>
&lt;p>See ya soon and keep committing!&lt;/p>
&lt;p>&amp;ndash;Chris&lt;/p></description></item><item><title>Better pull requests with git --autosquash</title><link>https://codegoalie.com/posts/2013-04-04-better-pull-requests-with-autosquash/</link><pubDate>Thu, 04 Apr 2013 00:00:00 +0000</pubDate><guid>https://codegoalie.com/posts/2013-04-04-better-pull-requests-with-autosquash/</guid><description>&lt;p>&lt;strong>UPDATE (Jun 7, 2013):&lt;/strong> I created an &lt;a href="http://ascii.io/a/3467">ascii.io video demo of
autosquash&lt;/a> for your viewing pleasure.&lt;/p>
&lt;p>Pull requests are an extremly crucial part of our workflow at Mobile
Defense. We pride ourselves on producing quality code and we do not
subscribe to the git-blame &amp;ldquo;I didn&amp;rsquo;t write it&amp;rdquo; culture. We all take
responsibility for all the code we produce, as a team. As such, being
able to review our code efficiently and thoroughly &lt;strong>before&lt;/strong> it gets
into &lt;code>master&lt;/code> is a goal we are constantly looking to improve upon.&lt;/p>
&lt;p>A somewhat paradox in reviewing code arises when the need for reviewers
to see the updates based on their feedback quickly and efficiently and
for the developer to be able to &amp;lsquo;fixup&amp;rsquo; their branch before merging to
ensure the code enters &lt;code>master&lt;/code> as cleanly as possible. That&amp;rsquo;s where
git-rebase comes in.&lt;/p>
&lt;p>Rebase is an extremely powerful tool in the git toolbelt. Combine
commits, edit commits in-place, rewrite history, etc. It&amp;rsquo;s especially
great for cleaning up your topic branches before submitting for code
review. However, remembering which commits need to be squashed into which
can be tricky especially when being the reviewee and the reviewer on
multiple pull requests daily. Well, it turns out git already has a really
clever, built-in way to organize and automate the branch cleanup process.
It is perfectly suited for making changes based on pull request feedback.
It&amp;rsquo;s called autosquash.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>Here was a typical pull request workflow:&lt;/p>
&lt;ol>
&lt;li>Code up a feature; commit early and often.&lt;/li>
&lt;li>Push to github and open a pull request.&lt;/li>
&lt;li>Do a quick self-review of my code.&lt;/li>
&lt;li>Ask others to review my code.&lt;/li>
&lt;li>Add temporary commits in response to comments.&lt;/li>
&lt;li>When the branch is approved for merge, rebase and fixup the
temporary commits into the original commits.&lt;/li>
&lt;li>Merge the branch.&lt;/li>
&lt;/ol>
&lt;p>As you might have experienced or noted in the workflow above, how do you
keep organized and remember which temporary commits should be squashed
into which original commits? The problem I ran into time and time
again was that as soon as I started an interactive rebase I would be
unable to remember exactly which commits needed to be changed, squashed,
or fixedup. So, I had been developing some commit message conventions for
temporary commits.&lt;/p>
&lt;p>For example, a commit which I knew was incomplete work or needed to be
looked at again would have it&amp;rsquo;s message prefixed with an excalmation
mark.&lt;/p>
&lt;pre>&lt;code>! Possible logic error in the complex_redirect logic
&lt;/code>&lt;/pre>
&lt;p>Further, commits which I knew I wanted to squash into previous commits
would be prefixed with four hyphens and have a message which I would be
able to make sense of when editing the rebase todo file.&lt;/p>
&lt;pre>&lt;code>---- into the first set of unit tests
&lt;/code>&lt;/pre>
&lt;p>This worked fairly well as long as I left myself good notes. But, surely
there must be a better way!&lt;/p>
&lt;h2 id="enter-autosquash">Enter autosquash&lt;/h2>
&lt;p>The &lt;code>--autosquash&lt;/code> flag on git-rebase is exactly what I was looking
for. During an interactive rebase, it processes messages to stage squashes
and fixups. These messages are setup with flags on git-commit at commit
time, which is when you are most likely to know what you ultimately
intend to do with commits. Further, it works via the commit message
so it&amp;rsquo;s easy for humans to understand as well!&lt;/p>
&lt;p>Say you have a feature branch with three commits: (viewing git logs with
the &lt;a href="https://codegoalie.com/2013/02/08/help-i-lost-a-commit-from-days-ago/#lg">incredibly awesome lg
alias&lt;/a>)&lt;/p>
&lt;pre>&lt;code>* cdaa049 (HEAD, features/new_hotness) Add new hotness to UI (66 seconds ago) &amp;lt;Chris Marshall&amp;gt;
* e14aa92 Implement new hotness backend (2 minutes ago) &amp;lt;Chris Marshall&amp;gt;
* 293070e Ensure new hotness works (2 minutes ago) &amp;lt;Chris Marshall&amp;gt;
* de72adc (origin/master, origin/HEAD, master) Add git internals meetup talk slides (6 months ago) &amp;lt;Chris Marshall&amp;gt;
&lt;/code>&lt;/pre>
&lt;p>Now let&amp;rsquo;s say you get a review comment on the commit for the tests
(&amp;lsquo;Ensure &amp;hellip;') which asks to add a test for a missed edge case.&lt;/p>
&lt;p>So we will code up our edge case fix and as we commit, we&amp;rsquo;ll add the
flag to specify what we ultimately will do with the commit.&lt;/p>
&lt;p>Git-commit has two such flags: &lt;code>--fixup&lt;/code> and &lt;code>--squash&lt;/code> with each of these
we will specify the commit &lt;strong>into which&lt;/strong> we want to fixup or squash. In
our example, we want to fixup into the first commit after master:
&lt;code>293070e&lt;/code>.&lt;/p>
&lt;p>We can do that with:&lt;/p>
&lt;pre>&lt;code>$ git commit --fixup=293070e
&lt;/code>&lt;/pre>
&lt;p>Which will produce a commmit with a message of:&lt;/p>
&lt;pre>&lt;code>fixup! Ensure new hotness works
&lt;/code>&lt;/pre>
&lt;p>A commit message formatted this way tells git-rebase (with &lt;code>--autosquash&lt;/code>)
to fix the patch in this commit up into the commit with the message &amp;ldquo;Ensure
new hotness works&amp;rdquo;. The power of using the commit message instead of SHA1
to identify commits is that this will work even after a rebase without
&lt;code>--autosquash&lt;/code> (e.g. pulling in lastest master changes).&lt;/p>
&lt;p>Here&amp;rsquo;s how it would look in github:&lt;/p>
&lt;p>&lt;img src="https://codegoalie.com/images/autosquash/fourth-commit.png" alt="Screenshot of Github PR with fixup commit linked incomment">&lt;/p>
&lt;p>&lt;em>Obviously, don&amp;rsquo;t have conversations with
yourself on github. This is purely educational ;)&lt;/em>&lt;/p>
&lt;hr>
&lt;p>Now the fun part! When the pull request is approved, you can rebase with
autosquash (and interactive) and watch as git does the work for you:&lt;/p>
&lt;pre>&lt;code>$ git rebase master -i --autosquash
&lt;/code>&lt;/pre>
&lt;p>Produces the rebase todo file:&lt;/p>
&lt;pre>&lt;code>pick 293070e Ensure new hotness works
fixup 3877fdf fixup! Ensure new hotness works
pick e14aa92 Implement new hotness backend
pick cdaa049 Add new hotness to UI
&lt;/code>&lt;/pre>
&lt;p>Simply save it and git rebases the branch as if you had changed the file
yourself. You can then merge and have a beer for all your efforts!&lt;/p>
&lt;h2 id="automating-autosquash">Automating autosquash&lt;/h2>
&lt;p>Adding the long &lt;code>--autosquash&lt;/code> flag all the time can get tiresome. Luckily,
you can add the &lt;code>rebase.autosquash&lt;/code> config value to run autosquash
automatically for every interactive rebase.&lt;/p>
&lt;pre>&lt;code>$ git config --global rebase.autosquash true
&lt;/code>&lt;/pre>
&lt;p>If no commits with the &lt;code>fixup!&lt;/code> or &lt;code>squash!&lt;/code> syntax are found, the rebase
continues normally. To override the autosquash default value, simply pass
the &lt;code>--no-autosquash&lt;/code> flag to rebase.&lt;/p>
&lt;p>Happy squashing!!&lt;/p>
&lt;p>&amp;ndash;Chris&lt;/p></description></item><item><title>Oh my! What large hot fixes you have</title><link>https://codegoalie.com/posts/2013-03-16-oh-my-what-large-hot-fixes-you-have/</link><pubDate>Tue, 26 Feb 2013 00:00:00 +0000</pubDate><guid>https://codegoalie.com/posts/2013-03-16-oh-my-what-large-hot-fixes-you-have/</guid><description>&lt;p>We&amp;rsquo;ve all been there: just finished a nice new feature, deployed it out
to production only to find that you&amp;rsquo;ve completely overlooked an edge
case or use case which is now totally breaking your app. Sometimes you
have to push a big hot fix. It has to get in immediately. It can&amp;rsquo;t wait
for writing correct tests or other better abstractions and
implementations. What to do? What to do?&lt;/p>
&lt;p>Well, there&amp;rsquo;s the common way of hacking as fast as you can until you&amp;rsquo;re
pretty sure the bug is fixed, commit everything in a big &amp;ldquo;Avert
crisis!!&amp;rdquo; commit. However, I think we can do better.&lt;/p>
&lt;p>First step checkout a new branch at your current &amp;lsquo;production,&amp;rsquo; or
similar. Call it production_pre_fix. Don&amp;rsquo;t check it out or work on it,
just leave it there as a placeholder.&lt;/p>
&lt;pre>&lt;code>$ git checkout production
$ git branch production_pre_fix
&lt;/code>&lt;/pre>
&lt;p>Now for the fun part: hack away! But, follow your usual development
practices of committing early and often. Refactor a method. Commit.
Add some if checks for edge cases. Commit. Get the shit fixed and
deployed. Go on. I&amp;rsquo;ll wait.&lt;/p>
&lt;p>Ok, alarms are quiet now and you&amp;rsquo;re done breaking shit? Good. Now
let&amp;rsquo;s get to work on the real fix. I&amp;rsquo;m glad your hacked together bunch
of duct tape fix is holding, but let&amp;rsquo;s not leave things like that. I
know you and I bet you&amp;rsquo;ve got some good work there. You probably don&amp;rsquo;t
want to just throw it all away. That&amp;rsquo;s cool. Why don&amp;rsquo;t we use the duct
tape as a basis for the permanent fix? Here&amp;rsquo;s how:&lt;/p>
&lt;p>First, get a clean branch off master&lt;/p>
&lt;pre>&lt;code>$ git checkout master
$ git checkout -b bugs/prod_fix
&lt;/code>&lt;/pre>
&lt;p>Then, write tests to account for your new found bugs.&lt;/p>
&lt;p>Next, cherry pick your current fix onto this branch.&lt;/p>
&lt;pre>&lt;code>$ git cherry-pick production_pre_fix..production
&lt;/code>&lt;/pre>
&lt;p>You may have noticed I passed two branch names with two periods in between to cherry-pick. What the fuck, right? Well, as we all know, two commit SHA1s separated by two periods is a range of commits. For exmple, &lt;!-- raw HTML omitted -->2e45f..34b79&lt;!-- raw HTML omitted -->. You are saying that you&amp;rsquo;d like to use all the commits starting at &lt;!-- raw HTML omitted -->34b79&lt;!-- raw HTML omitted --> and following parent links back until you reach &lt;!-- raw HTML omitted -->2e45f&lt;!-- raw HTML omitted -->.&lt;/p>
&lt;p>But I&amp;rsquo;ve used brach names here, which are just human friendly shortcuts
for SHA1s. Remember branch names are basically pointers to a particular
commit. They can be used in any git command which would otherwise take
a commit SHA1. Add that to the fact that cherry-pick can take a range
and suddenly your doing some pretty powerful stuff with a pretty simple
command. Go you!&lt;/p>
&lt;p>Now a little housekeeping,&lt;/p>
&lt;ul>
&lt;li>Make sure your fix actually passes your tests.&lt;/li>
&lt;li>Refactor and make your fix nice. Rebase, as necessary.&lt;/li>
&lt;li>Start pull request and get the feature merged back into master.&lt;/li>
&lt;/ul>
&lt;p>Then we need to reset your temp fix in production. Like this:&lt;/p>
&lt;pre>&lt;code>$ git checkout production
$ git reset --hard production_pre_fix
$ git branch -d production_pre_fix
$ git push -f
&lt;/code>&lt;/pre>
&lt;p>Woah woah woah! No, I didn&amp;rsquo;t. I just force pushed a non-topic branch.
Isn&amp;rsquo;t that a big no-no? Usually, yes and I would expect to be taken out
back and beaten until I learned my lesson. However, until I&amp;rsquo;m told of
a good reason otherwise: production or other released branches are not
shared among developers. They are an exact representation of what is
to be deployed next to the environment they represent.&lt;/p>
&lt;p>Why aren&amp;rsquo;t release branches an accurate representation of what is
currently deployed to the environment they represent? Because if you
want to know that, look at the environment. There&amp;rsquo;s no need for
duplicate information. A branch like production should be curated and
hold what will be deployed next to production. You might not do that
curating and updating until moments before the deploy. But for all
that time until you deploy, if you had to emergency deploy, whatever
is in the branch will be deployed.&lt;/p>
&lt;p>Back to business, we&amp;rsquo;ve reset production back to not include the duct
tape. Now it&amp;rsquo;s time to merge master and our fix up to it.&lt;/p>
&lt;pre>&lt;code>$ git checkout production
$ git merge master
&lt;/code>&lt;/pre>
&lt;p>Congratulations! You&amp;rsquo;ve not only saved your company from sure collapse
by fixing a huge production bug. But you&amp;rsquo;ve also reconciled your
technical debt and prevented other developers behind you from cursing
your name at the duct tape-y hacks you introduced to the code base.
That deserves a beer!&lt;/p>
&lt;p>&amp;ndash; Chris&lt;/p></description></item><item><title>Help! I lost a commit from days ago!!!</title><link>https://codegoalie.com/posts/2013-03-16-help-i-lost-a-commit-from-days-ago/</link><pubDate>Fri, 08 Feb 2013 00:00:00 +0000</pubDate><guid>https://codegoalie.com/posts/2013-03-16-help-i-lost-a-commit-from-days-ago/</guid><description>&lt;p>Oh no! I&amp;rsquo;m screwed! Better try to remember what work I did and recreate
it&amp;hellip; :( J/K! This is git! Of course there&amp;rsquo;s a slick way to recover what
you lost. Here&amp;rsquo;s my situation: I was working on a feature branch happily
coding away. Finished the feature, rebased it quickly to fix a typo and
then merged it into master. All&amp;rsquo;s well in my world. However, that was
days ago and today I just realized that I accidentally removed one of my
commits from the feature branch while I was working on it. No worries.
Here&amp;rsquo;s how I got the commit back with relative ease.&lt;/p>
&lt;p>&lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->
First, let me give you a lay of the land. I use the incredible git lg alias.&lt;/p>
&lt;pre>&lt;code>lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset' --abbrev-commit --
&lt;/code>&lt;/pre>
&lt;p>Seriously, steal that now. Use it a thousand times a day. I wish I
could attribute it to the original author, but I have since forgotten
where I originally saw it. At any rate, every few weeks I see it posted
anew on a different site.&lt;/p>
&lt;p>Anyway, here&amp;rsquo;s where I was at before the recovery:&lt;/p>
&lt;script type="text/javascript" src="https://gist.github.com/4738855.js?file=lost_commit.sh">&lt;/script>
&lt;p>Well&amp;hellip;now what? Redo all that work in the lost commit. Nah. Reflog to the rescue! Git&amp;rsquo;s &lt;!-- raw HTML omitted -->reflog&lt;!-- raw HTML omitted --> is a (by default) 90 day record of everywhere your HEAD ref was pointing. Anytime you do a checkout, create branch, commit, rebase; anytime the &amp;lsquo;current&amp;rsquo; commit of your working directory changes, the reflog gets a new entry. You can think of the reflog as a record of what you&amp;rsquo;ve been doing. If you&amp;rsquo;ve had it in your working directory in the past 30 days, it&amp;rsquo;s in the reflog.&lt;/p>
&lt;p>Remember what the commit message was for my lost commit? Nice! We can easily grep for it:&lt;/p>
&lt;pre>&lt;code>chrismar035:super_sweet_rails_app(master) $ git reflog | grep &amp;quot;commit message&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>What&amp;rsquo;s that? I didn&amp;rsquo;t tell you the commit message for the lost commit? Well, I don&amp;rsquo;t remember either! Now we are screwed.&lt;/p>
&lt;p>Gotcha again! We can still find it. We can use the ancient art of looking for what we lost. It&amp;rsquo;s easy. Simply do a &lt;!-- raw HTML omitted -->git reflog&lt;!-- raw HTML omitted --> and you will see a list of everywhere you&amp;rsquo;ve been:&lt;/p>
&lt;script type="text/javascript" src="https://gist.github.com/4738855.js?file=reflog.sh">&lt;/script>
&lt;p>AHA! Not only did you find the &lt;!-- raw HTML omitted -->LOST COMMIT!!!&lt;!-- raw HTML omitted -->, but we can also look at what happened too. Apparently, on a mad dash to get the feature merged before going out and getting my drink on with some chaps, I accidentally rebased my commit right out of the project. Damnit.&lt;/p>
&lt;p>Oh well, at least you found it for me. Thanks. Now, we&amp;rsquo;ve only got one real choice to fix this. We have to cherry-pick the commit out of the reflog back into master. Because I&amp;rsquo;ve already merged my feature branch into master and pushed it, I cannot go back and rebase or otherwise edit that pushed history of master. I&amp;rsquo;ve got to bite the bullet and add a commit straight onto master&amp;hellip; Everyone screws up once in a while.&lt;/p>
&lt;p>In the reflog, there are two ways to reference the commit: the SHA1 and the &lt;!-- raw HTML omitted -->HEAD@{integer}&lt;!-- raw HTML omitted --> reference. Either one will work. I like the SHA1 because I can double click in the terminal and it gets correctly highlighted for copying. Copy it and we&amp;rsquo;ll paste it back into the command line with:&lt;/p>
&lt;pre>&lt;code>chrismar035:super_sweet_rails_app(master) $ git cherry-pick 9a7de0e
&lt;/code>&lt;/pre>
&lt;p>&lt;code>lg&lt;/code> that again and see how we look:&lt;/p>
&lt;script type="text/javascript" src="https://gist.github.com/4738855.js?file=all_fixed.sh">&lt;/script>
&lt;p>Nice! Now, notice that the SHA1 changed from what you copied out of the reflog. Remember, commit SHA1s are based on their content (files, dirs, commit messages and meta data) AND their parent(s). So, if you change the parent of the commit, you change the commit (Same reason all the SHA1s change when you rebase). In reality, the commit you cherry-picked is duplicated on to the branch you cherry-pick it into. However, in our case that&amp;rsquo;s exactly what we wanted, because I messed up and deleted the commit in the first place.&lt;/p>
&lt;p>Nice work! Push and have a beer!! :)&lt;/p>
&lt;p>&amp;ndash; Chris&lt;/p></description></item></channel></rss>