Tyler Cipriani: pages tagged git
Tyler Cipriani
https://tylercipriani.com/tags/git/
Tyler Cipriani
ikiwiki
2019-03-21T15:53:53Z
Of Git Commits, GitHub, and Gerrit
https://tylercipriani.com/blog/2019/03/11/of-git-commits-github-and-gerrit/
Tyler Cipriani
Copyright © 2019 Tyler Cipriani
2019-03-21T15:53:53Z
2019-03-11T16:50:36Z
<p>Impassioned ranting about the format of commit messages<a href="https://tylercipriani.com/tags/git/#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a> often feels like cringe-inducing gatekeeping. Many times such rants seem to be written using language both bombastic and bellicose – the message is: fuck off if you don’t agree.</p>
<p>The fact that the authors of many of these rants tend to be respected in the software community is confounding to many. Defense of these rants is commonplace and, likewise, is swift, absolute, and equally, seemingly, meant as a giant middle-finger to the uninitiated.</p>
<p>Explaining new concepts to people unfamiliar with them is a good way of testing your understanding. Explaining new concepts repeatedly, in a seemingly unending cycle, is a good test of your patience. Neither lack of understanding or lack of patience excuse the bad behavior that is all-too-typical of the software hegemony.</p>
<p>This post is meant to explain when and why commit messages matter. Additionally, it explains a few thoughts about the Gerrit code review system.</p>
<section id="pull-request-vs-commit" class="level2">
<h2>Pull Request vs Commit <a href="https://tylercipriani.com/tags/git/#pull-request-vs-commit">¶</a></h2>
<p>The common wisdom is that commit messages don’t matter on GitHub. When I collaborate on GitHub I commit often and my commit messages frequently contain “.gif”, <code>¯\_(ツ)_/¯</code>, various curse words, and copious emoji. This is because the <a href="https://zachholman.com/posts/git-commit-history/">unit of change in GitHub is the pull request</a>. My pull requests are thoughtful, and attempt to explain why I developed this particular patch, and try to provide means of testing for this change. When trying to bisect history in a repository developed on GitHub the merges of pull requests are the thing; i.e., <code>Merge pull request #763</code> is meaningful. Pull request #763 probably has an explanation for what changed (even if your git log doesn’t).</p>
<p>The information contained in a pull request is useful, but is – by design – only accessible online with a web browser through github.com.</p>
<p>My current job uses <a href="https://gerrit.wikimedia.org/">Gerrit</a> instead of GitHub. Gerrit doesn’t have pull requests, it has patches. The code review interface is arguably not as good as GitHub <strike>– I can’t set a unified diff view by default in my preferences, for instance.</strike> (edit 2019-03-21. unified diff is available in top-level preferences) <a href="https://gerrit.googlesource.com/gitiles">Gitiles</a> is no substitute for using GitHub as a repo browser – you can’t link to blocks of code, for instance. Gerrit/Gitiles URLs are hard to remember, unlike GitHub’s. There is little in the way of a “prescribed workflow”. You as a developer must decide how to split patches meaningfully, and how to do that in such a way that adheres with any shared agreements about particular branches (e.g., <code>master</code> must be deployable).</p>
<p>Despite its flaws, I really like Gerrit.</p>
<p>Gerrit’s use of git aligns well with git’s design. The git history that Gerrit produces is beautiful, available offline, distributed, and useable via the git command line interface (more usable than in the browser, unfortunately). This is partially because the unit of change in Gerrit is a commit. As a result, <code>git log --oneline</code> is totally readable and totally useful!</p>
<p>I prefer the repo produced by Gerrit to the repo produced by GitHub for reasons that relate to development, operations, and values.</p>
</section>
<section id="development" class="level2">
<h2>Development <a href="https://tylercipriani.com/tags/git/#development">¶</a></h2>
<p>If I’m considering making a change in a repository, especially when this change is an obvious or simple one, I worry. I worry: why wasn’t this approach chosen in the first place? Is there a bug that is being worked around by using a non-obvious approach? Am I in an area of code that is used in many areas of the code base, or is it used very seldom? Is there test coverage for this function that I can use to ensure I am not creating a regression? A good commit message would answer all of these questions, and maybe more I haven’t thought of yet.</p>
<p>This information in Gerrit lives with the repository, in GitHub the information lives on github.com. It’s very important that the information exist <em>somewhere</em>.</p>
<p>I like the freedom to work on code when I’m on an airplane or somewhere else without WiFi. There may be software that can make this happen for GitHub. In Gerrit the unit-of-change is the Commit, so the commit has most information that I want. With the addition of the <a href="https://gerrit.wikimedia.org/r/Documentation/config-plugins.html#reviewnotes">review-notes</a> Gerrit plugin, code reviews live in a special git note namespace (<code>/refs/notes/review</code>) and are also available with the repository offline.</p>
<p>Gerrit makes no recommendations whatsoever about how you develop, and nothing in the patch interface aligns with your local view of your changes necessarily. I feel like this is confusing for people new to using Gerrit, but it is also, after initiation to the concept, not a bad way to develop.</p>
</section>
<section id="operations" class="level2">
<h2>Operations <a href="https://tylercipriani.com/tags/git/#operations">¶</a></h2>
<p>An appreciable portion of my job is <code>grep</code>ing through git history in the shaky moments following an embarrassing production outage. This exercise has given me a deep appreciation for well formatted git commit messages. I need to know: what changed, who changed it (not just who merged it), why it was changed, and why a particular approach was chosen.</p>
<p>Good commit message information helps me determine what to do with a change: do I need to wake up the person who made this commit, or can I simply revert it? Is this change merely setting an unused variable, or is it a feature flag that will unleash new functionality?</p>
<p>Having all this information at my fingertips, rather than having to dig through the 188(!) different repositories that are composed to create a production deployment of MediaWiki and extensions for all 933 wikis that exist in Wikimedia’s production infrastructure is important – I already have too many browser tabs open without having to dig through GitHub for repository histories.</p>
</section>
<section id="values" class="level2">
<h2>Values <a href="https://tylercipriani.com/tags/git/#values">¶</a></h2>
<p>This section speaks more to my feelings about Gerrit vs GitHub as projects more than Gerrit vs GitHub repositories. In the case of GitHub’s use of pull requests, I feel like the two are inextricably linked – GitHub has opted out of the open source implementation of git using proprietary software to implement this feature and the resultant repository is less usable as an artifact on its own because of this decision.</p>
<p>The essay <a href="https://mako.cc/writing/hill-free_tools.html">Free software needs Free tools</a> is probably a better summary of this topic than anything I could write here; however, the short version of this is: without the freedom to run, modify, study, and redistribute the software on which your project depends, your project is at the mercy of corporate caprice.</p>
<p>Corporations are beholden to shareholders, not to users. When a corporation pivots away from the customers that made it a success to serve a different market that it perceives as more valuable that is not an uncommon or remarkable event: that is the design of a corporation.</p>
<p>If you are working on a software project that’s important – if your software provides an essential service, or essential infrastructure that is meant to last many years (even beyond a single human lifetime) – you cannot afford to lose a part of your infrastructure in the event that a (possibly erroneous) business analysis has identified a more efficient profit-center for a business.</p>
<p>There are many counter-arguments to the ones I’ve made above; however, to summarize a few counter-arguments (possibly unfairly) they are:</p>
<ol type="1">
<li><code><Closed Source/Hosted provider></code>‘s core business is acting in their customers’ best interest, if its goal is to provide value to shareholders then to do so means being a better service for its existing customers. Our interests and the business’s interests are aligned.</li>
<li><code><Closed Source/Hosted provider></code> is based on an open standard, so the information is portable, if they become a bad actor, we can port information to a different solution.</li>
</ol>
<p>To argument one: there are myriad examples of business decisions made at the expense of customers. This is particularly true once a business entity becomes a monopoly power as so many tech companies are at this moment. I think anyone would concede the example of large cable companies offering poor service to customers despite the fact that customers provide their revenue. Business interests and customer interests, even when they are currently aligned, may not always be.</p>
<p>To argument two: in the instance of GitHub above (and this is applicable to other services as well) they have proprietary features (i.e., “pull requests”) that make them incompatible with portability. In other instances, the compatibility with a portable solution is invalidated by the point of business caprice.</p>
</section>
<section id="how-i-commit-now" class="level2">
<h2>How I commit now <a href="https://tylercipriani.com/tags/git/#how-i-commit-now">¶</a></h2>
<p>If commit messages are important (as I argue above), then it is a valuable exercise to evaluate the way in which you write your commit messages.</p>
<p>Earlier this year I came across Vicky Lai’s post “<a href="https://vickylai.com/verbose/git-commit-practices-your-future-self-will-thank-you-for/">Git Commit Practices Your Future Self Will Thank You For</a>” Which (for me anyway) highlighted the use of the git <code>commit.template</code>. Vicky provided an example in the post that I’ve been refining for myself.</p>
<p>I’ve followed git commit best practices<a href="https://tylercipriani.com/tags/git/#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a><a href="https://tylercipriani.com/tags/git/#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a><a href="https://tylercipriani.com/tags/git/#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> for years, so initially the template wasn’t proving too useful. I started to think about what was missing from my commit messages, where I could improve formatting, and where I could save myself some time searching.</p>
<p>The first issue I identified is that I can’t remember the names of commit message fields like <code>Signed-off-by</code> or <code>Requested-by</code>. Also, my capitalization and ordering of those fields was all over the place. What are the best-practices for using these fields? I could never remember. I put all these fields in my template. Along with a link to the kernel patch submission guidelines for easy reference.</p>
<p>The next issue I had was that there are myriad schools of thought about commit message bodies. Bullet points vs Problem/Solution vs “answers the following questions”. The basic questions of “What is wrong with the code that this patch fixes?” sometimes hindered my ability to write a commit message that made sense. I wanted options. I wanted examples. I wanted links in case I felt like reading more. I added all this to my template.</p>
<p>Finally, I noticed that vim does some syntax highlighting in the commit screen. Specifically, lines that end with <code>:</code>. So I made sure that the only lines that ended with <code>:</code> were important sections.</p>
<p>I think I have a template I can live with for a while. It’s verbose. Probably too verbose, really. But my mind works in ways I don’t understand sometimes. To keep it on track, I need all the information it craves at my fingertips in a context-dependant way. I think this template is ideal for that.</p>
</section>
<section id="git-commit-zomg1" class="level2">
<h2>Git Commit ZOMG!!1! <a href="https://tylercipriani.com/tags/git/#git-commit-zomg1">¶</a></h2>
<p>The <code>commit.template</code> below is in my dotfiles as <code>.git-commit-zomg</code>. I install the template using the command <code>git config --global commit.template ~/.git-commit-zomg</code>.</p>
<p>I named this template <code>.git-commit-zomg</code> because I have mixed feelings about commit messages. I think a lot about commit messages. I think they’re important. I evidently feel that they’re “rant worthy” in some context. I still, however, know people will decide the value of commit messages on their own. You can tell people the value you think commit messages will have, and they’ll maybe ackowledge your concerns are valid. Maybe they’ll even make changes in their process. But no one groks to fullness.</p>
<p>Someday production will be down. Rollback will have failed with an opaque error. Your mind will be screaming too loud for you to think clearly. You’ll frantically <code>grep</code> <code>git log</code> output for the error message – something, anything – and you’ll come face-to-face with a commit (probably authored by you) that reads, simply, <code>¯\_(ツ)_/¯</code>. To paraphrase Jack Handy: when this moment comes, if you’re drinking milk, I bet it will make milk come out your nose.</p>
<pre><code>
# ^^ Subject: summary of your change:
# * 50 Characters is a soft limit (aim for < 80)
# * "If applied, this commit will..."
# * Use the imperative mood; e.g.,
# (Change/Add/Fix/Remove/Update/Refactor/Document)
# * Do not end the subject with a period (full stop)
# * Optionally, prefix the subject with the relevant component
# (the general area of code being modified)
#
# Example[0]
#
# jquery.badge: Add ability to display the number zero
#
# [0]. <https://www.mediawiki.org/wiki/Gerrit/Commit_message_guidelines#Subject>
#
# Leave this blank line below your subject:
# Body: Additional information about a commit:
# Think about these questions
#
# * Why should this change should be made?
# What is wrong with the current code?
# * Why should it be changed in this way?
# Are there other ways?
# * How can a reviewer confirm that your change works as intended?[0]
#
# * An alternative format maybe a problem/solution commit as used in
# ZeroMQ[1]; e.g.
#
# * Problem: Windows build script requires edit of VS version
# * Solution: Use CMD.EXE environment variable to extract
# DevStudio version number and build using it.
#
# [0]. <https://www.mediawiki.org/wiki/Gerrit/Commit_message_guidelines#Body>
# [1]. <http://zeromq.org/docs:contributing#toc3>
# ---
#
# Bug number:
#
# Bug: TXXXXXX
#
# ---
#
# Gerrit specific:
#
# Change-Id: IXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Depends-On: IXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#
# ---
#
# Sign your work:
#
# > The sign-off is a simple line at the end of the explanation for the
# > patch, which certifies that you wrote it or otherwise have the right to
# > pass it on as a open-source patch [0]
#
# Signed-off-by: Example User <user@example.com>
#
# [0]. <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/SubmittingPatches?id=4e8a2372f9255a1464ef488ed925455f53fbdaa1>
#
# ---
#
# Other Nice Things:
#
# If you worked on a patch with others it's nice to credit them for
# their contributions; however, these tags should not be added without
# your collaborator's permission!
# Acked-by: Example User <user@example.com>
# Cc: Example User <user@example.com>
# Co-Authored-by: Example User <user@example.com>
# Requested-by: Example User <user@example.com>
# Reported-by: Example User <user@example.com>
# Reviewed-by: Example User <user@example.com>
# Suggested-by: Example User <user@example.com>
# Tested-by: Example User <user@example.com>
# Thanks: Example User <user@example.com>
#
# ---
# _ _ _ _
# __ _(_) |_ ___ ___ _ __ ___ _ __ ___ (_) |_ _______ _ __ ___ __ _
# / _` | | __| / __/ _ \| '_ ` _ \| '_ ` _ \| | __| |_ / _ \| '_ ` _ \ / _` |
# | (_| | | |_ | (_| (_) | | | | | | | | | | | | |_ / / (_) | | | | | | (_| |
# \__, |_|\__| \___\___/|_| |_| |_|_| |_| |_|_|\__| /___\___/|_| |_| |_|\__, |
# |___/ |___/
#
# Save to `~/.git-commit-zomg` Then run:
#
# git config --global commit.template ~/.git-commit-zomg
#
# The idea for this template came from Vicky Lai[0]
#
# [0]. <https://vickylai.com/verbose/git-commit-practices-your-future-self-will-thank-you-for/></code></pre>
</section>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://github.com/torvalds/linux/pull/17#issuecomment-5654674" class="uri">https://github.com/torvalds/linux/pull/17#issuecomment-5654674</a><a href="https://tylercipriani.com/tags/git/#fnref1" class="footnote-back">↩</a></p></li>
<li id="fn2"><p><a href="https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html" class="uri">https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html</a><a href="https://tylercipriani.com/tags/git/#fnref2" class="footnote-back">↩</a></p></li>
<li id="fn3"><p><a href="https://www.mediawiki.org/wiki/Gerrit/Commit_message_guidelines" class="uri">https://www.mediawiki.org/wiki/Gerrit/Commit_message_guidelines</a><a href="https://tylercipriani.com/tags/git/#fnref3" class="footnote-back">↩</a></p></li>
<li id="fn4"><p><a href="https://juffalow.com/other/write-good-git-commit-message" class="uri">https://juffalow.com/other/write-good-git-commit-message</a><a href="https://tylercipriani.com/tags/git/#fnref4" class="footnote-back">↩</a></p></li>
</ol>
</section>
Git Annex Metadata Filtered Views
https://tylercipriani.com/blog/2016/09/28/git-annex-metadata-filtered-views/
Tyler Cipriani
Creative Commons Attribution-ShareAlike License
Copyright © 2017 Tyler Cipriani
2017-10-12T03:25:12Z
2016-09-29T03:30:55Z
<p>Git annex goes mindbogglingly deep.</p>
<p>I use git annex to manage my photos – I have tons of RAW photos in <code>~/Pictures</code> that are backed-up to a few git annex special remotes.</p>
<p>Whenever I'm done editing a set of raw files I go through this song and dance:</p>
<div class="sourceCode" id="cb1" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="bu">cd</span> raw</a>
<a class="sourceLine" id="cb1-2" title="2"><span class="fu">git</span> annex add</a>
<a class="sourceLine" id="cb1-3" title="3"><span class="fu">git</span> annex copy --to=s3</a>
<a class="sourceLine" id="cb1-4" title="4"><span class="fu">git</span> annex copy --to=nas</a>
<a class="sourceLine" id="cb1-5" title="5"><span class="fu">git</span> commit -m <span class="st">'Added a bunch of files to s3'</span></a>
<a class="sourceLine" id="cb1-6" title="6"><span class="fu">git</span> push origin master</a>
<a class="sourceLine" id="cb1-7" title="7"><span class="fu">git</span> push origin git-annex</a>
<a class="sourceLine" id="cb1-8" title="8"><span class="fu">git</span> annex drop</a></code></pre></div>
<p>And magically my raw files are available on s3 and my home NAS.</p>
<p>If I jump over to a different machine I can run:</p>
<div class="sourceCode" id="cb2" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="bu">cd</span> ~/Pictures</a>
<a class="sourceLine" id="cb2-2" title="2"><span class="fu">git</span> fetch</a>
<a class="sourceLine" id="cb2-3" title="3"><span class="fu">git</span> rebase</a>
<a class="sourceLine" id="cb2-4" title="4"><span class="fu">git</span> annex get [new-raw-file]</a></code></pre></div>
<p>Now that raw file is available on my new machine, I can open it in Darktable, I can do whatever I want to it: it's just a file.</p>
<p>This is a pretty powerful extension of git.</p>
<p>While I was reading the <a href="https://git-annex.branchable.com/internals/">git annex internals</a> page today I stumbled across an even more powerful feature: metadata. You can store and retrieve arbitrary metadata about any git annex file. For instance, if I wanted to store EXIF info for a particular file, I could do:</p>
<div class="sourceCode" id="cb3" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" title="1"><span class="fu">git</span> annex metadata 20140118-BlazeyAndTyler.jpg --set exif=<span class="st">"</span><span class="va">$(</span><span class="ex">exiftool</span> -S \</a>
<a class="sourceLine" id="cb3-2" title="2"> -filename \</a>
<a class="sourceLine" id="cb3-3" title="3"> -filetypeextensions \</a>
<a class="sourceLine" id="cb3-4" title="4"> -make \</a>
<a class="sourceLine" id="cb3-5" title="5"> -model \</a>
<a class="sourceLine" id="cb3-6" title="6"> -lensid \</a>
<a class="sourceLine" id="cb3-7" title="7"> -focallength \</a>
<a class="sourceLine" id="cb3-8" title="8"> -fnumber \</a>
<a class="sourceLine" id="cb3-9" title="9"> -iso 20140118-BlazeyAndTyler.jpg<span class="va">)</span><span class="st">"</span></a></code></pre></div>
<p>And I can drop that file and still retrieve the EXIF data</p>
<div class="sourceCode" id="cb4" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb4-1" title="1">$ <span class="fu">git</span> annex drop 20140118-BlazeyAndTyler.jpg</a>
<a class="sourceLine" id="cb4-2" title="2"><span class="ex">drop</span> 20140118-BlazeyAndTyler.jpg (checking tylercipriani-raw...) <span class="kw">(</span><span class="ex">checking</span> tylercipriani-raw...<span class="kw">)</span> <span class="kw">(</span><span class="ex">checking</span> tylercipriani-raw...<span class="kw">)</span> <span class="ex">ok</span></a>
<a class="sourceLine" id="cb4-3" title="3"><span class="kw">(</span><span class="ex">recording</span> state in git...<span class="kw">)</span></a>
<a class="sourceLine" id="cb4-4" title="4">$ <span class="fu">git</span> annex metadata --get exif !$</a>
<a class="sourceLine" id="cb4-5" title="5"><span class="fu">git</span> annex metadata --get exif 20140118-BlazeyAndTyler.jpg</a>
<a class="sourceLine" id="cb4-6" title="6"><span class="ex">FileName</span>: 20140118-BlazeyAndTyler.jpg</a>
<a class="sourceLine" id="cb4-7" title="7"><span class="ex">Make</span>: SAMSUNG</a>
<a class="sourceLine" id="cb4-8" title="8"><span class="ex">Model</span>: SPH-L720</a>
<a class="sourceLine" id="cb4-9" title="9"><span class="ex">FocalLength</span>: 4.2 mm</a>
<a class="sourceLine" id="cb4-10" title="10"><span class="ex">FNumber</span>: 2.2</a>
<a class="sourceLine" id="cb4-11" title="11"><span class="ex">ISO</span>: 125</a></code></pre></div>
<p>This is pretty neat, but it can also be achieved with <a href="https://tylercipriani.com/blog/2016/08/26/abusing-git-notes/">git notes</a> so it's nothing too spectacular.</p>
<p>But git annex metadata doesn't quite stop there.</p>
<section id="random-background" class="level2">
<h2>Random background <a href="https://tylercipriani.com/tags/git/#random-background">¶</a></h2>
<p>My picture directory is laid out like this:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode txt"><code class="sourceCode default"><a class="sourceLine" id="cb5-1" title="1">Pictures/</a>
<a class="sourceLine" id="cb5-2" title="2">└── 2015</a>
<a class="sourceLine" id="cb5-3" title="3"> └── 2015-08-14_Project-name</a>
<a class="sourceLine" id="cb5-4" title="4"> ├── bin</a>
<a class="sourceLine" id="cb5-5" title="5"> │ └── convert-and-resize.sh</a>
<a class="sourceLine" id="cb5-6" title="6"> ├── edit</a>
<a class="sourceLine" id="cb5-7" title="7"> │ ├── 2015-08-14_Project-name_00001.jpg</a>
<a class="sourceLine" id="cb5-8" title="8"> │ └── 2015-08-14_Project-name_00002.jpg</a>
<a class="sourceLine" id="cb5-9" title="9"> └── raw</a>
<a class="sourceLine" id="cb5-10" title="10"> └── 2015-08-14_Project-name_00001.NEF</a></code></pre></div>
<p>I have directories for each year, under those directories I create directories that are prefixed with the <a href="https://xkcd.com/1179/">ISO 8601</a> import date for the photo, some memorable project name (like <code>mom-birthday</code> or <code>rmnp-hike</code>). Inside that directory I have 2 directories: <code>raw</code> and <code>edit</code>. Inside each one of those directories, I have photos that are named with ISO 8601 import date, project name, and 5-digit import number and a file extension – raw files go in <code>raw</code> and edited/finished files <code>edit</code>.</p>
<p>I got this system from <a href="http://www.rileybrandt.com/lessons/">Riley Brandt</a> (I can't recommend the Open Source Photography Course enough – it's amazing!) and it's served me well. I can find stuff! But git annex really expands the possibilities of this system.</p>
</section>
<section id="fictional-real-world-totally-real-actually-happening-scenario" class="level2">
<h2>Fictional, real-world, totally real actually happening scenario <a href="https://tylercipriani.com/tags/git/#fictional-real-world-totally-real-actually-happening-scenario">¶</a></h2>
<p>I go to Rocky Mountain National Park (RMNP) multiple times per year. I've taken a lot of photos there. If I take a trip there in October I will generally import those photos in October and create <code>2015/2015-10-05_RMNP-hike/{raw,edit}</code>, and then if I go there again next March I'd create <code>2016/2016-03-21_RMNP-daytrip-with-blazey/{raw,edit}</code>. So if I want to preview my RMNP edited photos from October I'd go:</p>
<div class="sourceCode" id="cb6" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb6-1" title="1"><span class="bu">cd</span> 2015/2015-10-05_RMNP-hike/edit</a>
<a class="sourceLine" id="cb6-2" title="2"><span class="fu">git</span> annex get</a>
<a class="sourceLine" id="cb6-3" title="3"><span class="ex">geeqie</span> .</a></code></pre></div>
<p>But what happens if I want to see all the photos I've ever taken in RMNP? I could probably cook up some script to do this. Off the top of my head I could do something like <code>find . -iname '*rmnp*' -type l</code>, but that would undoubtedly miss some files from a project in RMNP that I didn't name with the string <code>rmnp</code>. Git annex gives me a different option: metadata tags.</p>
</section>
<section id="metadata-tags" class="level2">
<h2>Metadata Tags <a href="https://tylercipriani.com/tags/git/#metadata-tags">¶</a></h2>
<p>Git annex supports a special type of short metadata – <code>--tag</code>. With <code>--tag</code>, you can tag individual files in your repo.</p>
<p>The WMF reading team offsite in 2016 was partially in RMNP, but I didn't name any photos <code>RMNP</code> because that wasn't the most memorable bit of information about those photos (<code>reading-team-offsite</code> seemed like a better project name) nor did <code>RMNP</code> represent all the photos from the offsite. I should tag a few of those photos <code>rmnp</code> with git annex:</p>
<div class="sourceCode" id="cb7" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb7-1" title="1">$ <span class="bu">cd</span> ./2016/2016-05-01_wikimedia-reading-offsite/edit/</a>
<a class="sourceLine" id="cb7-2" title="2">$ <span class="fu">git</span> annex metadata --tag rmnp Elk.jpg</a>
<a class="sourceLine" id="cb7-3" title="3"><span class="ex">metadata</span> Elk.jpg </a>
<a class="sourceLine" id="cb7-4" title="4"> <span class="va">lastchanged=</span>2016-09-29<span class="ex">@04-14-44</span></a>
<a class="sourceLine" id="cb7-5" title="5"> <span class="va">tag=</span>rmnp</a>
<a class="sourceLine" id="cb7-6" title="6"> <span class="ex">tag-lastchanged</span>=2016-09-29@04-14-44</a>
<a class="sourceLine" id="cb7-7" title="7"><span class="ex">ok</span></a>
<a class="sourceLine" id="cb7-8" title="8"><span class="kw">(</span><span class="ex">recording</span> state in git...<span class="kw">)</span></a>
<a class="sourceLine" id="cb7-9" title="9">$ <span class="fu">git</span> annex metadata --tag rmnp Reading<span class="dt">\ </span>folks<span class="dt">\ </span>bing<span class="dt">\ </span>higher<span class="dt">\ </span>up<span class="dt">\ </span>than<span class="dt">\ </span>it<span class="dt">\ </span>looks.jpg</a>
<a class="sourceLine" id="cb7-10" title="10"><span class="ex">metadata</span> Reading folks bing higher up than it looks.jpg </a>
<a class="sourceLine" id="cb7-11" title="11"> <span class="va">lastchanged=</span>2016-09-29<span class="ex">@04-14-57</span></a>
<a class="sourceLine" id="cb7-12" title="12"> <span class="va">tag=</span>rmnp</a>
<a class="sourceLine" id="cb7-13" title="13"> <span class="ex">tag-lastchanged</span>=2016-09-29@04-14-57</a>
<a class="sourceLine" id="cb7-14" title="14"><span class="ex">ok</span></a>
<a class="sourceLine" id="cb7-15" title="15"><span class="kw">(</span><span class="ex">recording</span> state in git...<span class="kw">)</span></a></code></pre></div>
<p>Also, when my old roommate came to town we went to RMNP, but I tagged those photos <code>cody-family-adventure-time</code>. So let's tag a few of those <code>rmnp</code>, too:</p>
<div class="sourceCode" id="cb8" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb8-1" title="1">$ <span class="bu">cd</span> 2015/2016-01-25_cody-family-adventuretime/edit</a>
<a class="sourceLine" id="cb8-2" title="2">$ <span class="fu">git</span> annex metadata --tag rmnp alberta-falls.jpg</a>
<a class="sourceLine" id="cb8-3" title="3"><span class="ex">metadata</span> alberta-falls.jpg </a>
<a class="sourceLine" id="cb8-4" title="4"> <span class="va">lastchanged=</span>2016-09-29<span class="ex">@04-17-48</span></a>
<a class="sourceLine" id="cb8-5" title="5"> <span class="va">tag=</span>rmnp</a>
<a class="sourceLine" id="cb8-6" title="6"> <span class="ex">tag-lastchanged</span>=2016-09-29@04-17-48</a>
<a class="sourceLine" id="cb8-7" title="7"><span class="ex">ok</span></a>
<a class="sourceLine" id="cb8-8" title="8"><span class="kw">(</span><span class="ex">recording</span> state in git...<span class="kw">)</span></a></code></pre></div>
</section>
<section id="metadata-views" class="level2">
<h2>Metadata views <a href="https://tylercipriani.com/tags/git/#metadata-views">¶</a></h2>
<p>Now the thing that was really surprising to me, you can filter the whole pictures directory based on a particular tag with git annex by using a <a href="https://git-annex.branchable.com/tips/metadata_driven_views/">metadata driven view</a>.</p>
<div class="sourceCode" id="cb9" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb9-1" title="1">$ <span class="ex">tree</span> -d -L 1</a>
<a class="sourceLine" id="cb9-2" title="2"><span class="ex">.</span></a>
<a class="sourceLine" id="cb9-3" title="3">├── <span class="ex">2011</span></a>
<a class="sourceLine" id="cb9-4" title="4">├── <span class="ex">2012</span></a>
<a class="sourceLine" id="cb9-5" title="5">├── <span class="ex">2013</span></a>
<a class="sourceLine" id="cb9-6" title="6">├── <span class="ex">2014</span></a>
<a class="sourceLine" id="cb9-7" title="7">├── <span class="ex">2015</span></a>
<a class="sourceLine" id="cb9-8" title="8">├── <span class="ex">2016</span></a>
<a class="sourceLine" id="cb9-9" title="9">├── <span class="ex">instagram</span></a>
<a class="sourceLine" id="cb9-10" title="10">├── <span class="ex">lib</span></a>
<a class="sourceLine" id="cb9-11" title="11">├── <span class="ex">lossy</span></a>
<a class="sourceLine" id="cb9-12" title="12">├── <span class="ex">nasa</span></a>
<a class="sourceLine" id="cb9-13" title="13">└── <span class="ex">Webcam</span></a>
<a class="sourceLine" id="cb9-14" title="14"></a>
<a class="sourceLine" id="cb9-15" title="15">$ <span class="fu">git</span> annex view tag=rmnp</a>
<a class="sourceLine" id="cb9-16" title="16"><span class="ex">view</span> (searching...) </a>
<a class="sourceLine" id="cb9-17" title="17"><span class="ex">Switched</span> to branch <span class="st">'views/(tag=rmnp)'</span></a>
<a class="sourceLine" id="cb9-18" title="18"><span class="ex">ok</span></a>
<a class="sourceLine" id="cb9-19" title="19">$ <span class="fu">ls</span></a>
<a class="sourceLine" id="cb9-20" title="20"><span class="ex">alberta-falls_%2015%2016-01-25_cody-family-adventuretime%edit%.jpg</span></a>
<a class="sourceLine" id="cb9-21" title="21"><span class="ex">Elk_%2016%2016-05-01_wikimedia-reading-offsite%edit%.jpg</span></a>
<a class="sourceLine" id="cb9-22" title="22"><span class="ex">Reading</span> folks bing higher up than it looks_%2016%2016-05-01_wikimedia-reading-offsite%edit%.jpg</a></code></pre></div>
<p>I can even filter this view using other tags with <code>git annex vfilter tag=whatever</code>. And I can continue to edit, refine, and work with the photo files from there.</p>
<p>This feature absolutely blew my mind – I dropped what I was doing to write this – I'm trying to think of a good way to work it into my photo workflow <img src="https://tylercipriani.com/smileys/smile.png" alt=":)" /></p>
</section>
Git-Config Colors and Include
https://tylercipriani.com/blog/2016/09/21/git-config-include-and-colors/
Tyler Cipriani
Creative Commons Attribution-ShareAlike License
Copyright © 2017 Tyler Cipriani
2017-02-14T15:11:05Z
2016-09-22T00:56:33Z
<p>While I was looking through my <code>~/.gitconfig</code> today, I learned some new tricks.</p>
<p>I've had the <code>color</code> section in my <code>~/.gitconfig</code> without really understanding it:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode ini"><code class="sourceCode ini"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">[color]</span></a>
<a class="sourceLine" id="cb1-2" title="2"><span class="dt"> ui </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span></a></code></pre></div>
<p>First, it seems that <code>git config color.ui true</code> is superfluous as it has been set to <code>true</code> by default since Git 1.8.4. More importantly, I learned that you can customize the colors of <code>git-branch</code>, <code>git-diff</code>, <code>git-status</code>, <code>git log --decorate</code>, <code>git-grep</code>, and <code>git {add,clean} --interactive</code></p>
<p>The easiest way I could find to view what properties are available to colorize is to search for <code><slot></code> on the git-config man page.</p>
<p>The other neat thing I learned is that you can include other config files by adding an <code>include</code> section in your <code>~/.gitconfig</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode ini"><code class="sourceCode ini"><a class="sourceLine" id="cb2-1" title="1"><span class="kw">[include]</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="dt"> path </span><span class="ot">=</span><span class="st"> ~/.config/git/colors.config</span></a></code></pre></div>
<p>By combining these two tricks, you can create one colorscheme for a terminal that uses the <a href="https://github.com/ChrisKempson/Tomorrow-Theme">Tomorrow Theme</a> and one for the terminal that uses <a href="http://ethanschoonover.com/solarized">Solarized</a> and swap between them easily by swapping the symlink pointed at by <code>~/.config/git/color.config</code></p>
<div class="sourceCode" id="cb3"><pre class="sourceCode ini"><code class="sourceCode ini"><a class="sourceLine" id="cb3-1" title="1"><span class="co"># Tomorrow Night Eighties in ~/.config/git/tomorrow-night-eighties.config</span></a>
<a class="sourceLine" id="cb3-2" title="2"><span class="co"># Included in ~/.gitconfig via:</span></a>
<a class="sourceLine" id="cb3-3" title="3"><span class="co"># [include]</span></a>
<a class="sourceLine" id="cb3-4" title="4"><span class="co"># path = ~tyler/.config/git/tomorrow-night-eighties.config</span></a>
<a class="sourceLine" id="cb3-5" title="5"><span class="kw">[color "status"]</span></a>
<a class="sourceLine" id="cb3-6" title="6"><span class="dt"> header </span><span class="ot">=</span><span class="st"> "#</span><span class="dv">999999</span><span class="st">"</span></a>
<a class="sourceLine" id="cb3-7" title="7"><span class="dt"> added </span><span class="ot">=</span><span class="st"> "#99cc99"</span></a>
<a class="sourceLine" id="cb3-8" title="8"><span class="dt"> changed </span><span class="ot">=</span><span class="st"> "#f2777a"</span></a>
<a class="sourceLine" id="cb3-9" title="9"><span class="dt"> untracked </span><span class="ot">=</span><span class="st"> "#ffcc66"</span></a>
<a class="sourceLine" id="cb3-10" title="10"><span class="dt"> branch </span><span class="ot">=</span><span class="st"> "#2d2d2d" "#6699cc"</span></a>
<a class="sourceLine" id="cb3-11" title="11"><span class="dt"> </span><span class="co"># Because the phrase "Detached HEAD" isn't unnerving enough</span></a>
<a class="sourceLine" id="cb3-12" title="12"><span class="dt"> nobranch </span><span class="ot">=</span><span class="st"> bold ul blink "#f99157"</span></a>
<a class="sourceLine" id="cb3-13" title="13"><span class="kw">[color "diff"]</span></a>
<a class="sourceLine" id="cb3-14" title="14"><span class="dt"> meta </span><span class="ot">=</span><span class="st"> "#</span><span class="dv">515151</span><span class="st">"</span></a>
<a class="sourceLine" id="cb3-15" title="15"><span class="dt"> func </span><span class="ot">=</span><span class="st"> "#cc99cc"</span></a>
<a class="sourceLine" id="cb3-16" title="16"><span class="dt"> frag </span><span class="ot">=</span><span class="st"> "#66cccc"</span></a>
<a class="sourceLine" id="cb3-17" title="17"><span class="dt"> context </span><span class="ot">=</span><span class="st"> "#</span><span class="dv">999999</span><span class="st">"</span></a>
<a class="sourceLine" id="cb3-18" title="18"><span class="dt"> old </span><span class="ot">=</span><span class="st"> "#f2777a" "#</span><span class="dv">393939</span><span class="st">"</span></a>
<a class="sourceLine" id="cb3-19" title="19"><span class="dt"> new </span><span class="ot">=</span><span class="st"> "#bef2be" "#</span><span class="dv">515151</span><span class="st">"</span></a></code></pre></div>
<p>I wish the symlink swap didn't have to happen – I wish you could just use environment variables.</p>
<p>As far as I can tell the only variables that are expanded in <code>~/.gitconfig</code> are <code>~</code> to point at the current user's home directory and <code>~[user]</code> points to <code>[user]</code>'s home directory.</p>
<p><code>include</code> also fails silently by design.</p>
<p>I feel like there are some other neat tricks to uncover here, but I haven't quite grokked this to fullness just yet.</p>
Delete Local Git Commits
https://tylercipriani.com/blog/2016/09/07/delete-local-git-commits/
Tyler Cipriani
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike License</a>
Copyright © 2017 Tyler Cipriani
2017-07-01T00:49:09Z
2016-09-07T17:48:08Z
<p>Usually when I need to delete a commit from a local git repo I use:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="fu">git</span> rebase -i</a></code></pre></div>
<p>This starts an interactive rebase session for all commits from <code>HEAD..@{u}</code>. Once I’m in the git rebase editor I put a <code>drop</code> on the line that has the commit I want to delete and save the file. Magic. Commit gone.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="ex">drop</span> c572357 [LOCAL] Change to be removed</a>
<a class="sourceLine" id="cb2-2" title="2"></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="co"># Rebase dbfcb3a..c572357 onto dbfcb3a (1 command(s))</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="co">#</span></a>
<a class="sourceLine" id="cb2-5" title="5"><span class="co"># Commands:</span></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="co"># p, pick = use commit</span></a>
<a class="sourceLine" id="cb2-7" title="7"><span class="co"># r, reword = use commit, but edit the commit message</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="co"># e, edit = use commit, but stop for amending</span></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="co"># s, squash = use commit, but meld into previous commit</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="co"># f, fixup = like "squash", but discard this commit's log message</span></a>
<a class="sourceLine" id="cb2-11" title="11"><span class="co"># x, exec = run command (the rest of the line) using shell</span></a>
<a class="sourceLine" id="cb2-12" title="12"><span class="co"># d, drop = remove commit</span></a>
<a class="sourceLine" id="cb2-13" title="13"><span class="co">#</span></a>
<a class="sourceLine" id="cb2-14" title="14"><span class="co"># These lines can be re-ordered; they are executed from top to bottom.</span></a>
<a class="sourceLine" id="cb2-15" title="15"><span class="co">#</span></a>
<a class="sourceLine" id="cb2-16" title="16"><span class="co"># If you remove a line here THAT COMMIT WILL BE LOST.</span></a>
<a class="sourceLine" id="cb2-17" title="17"><span class="co">#</span></a>
<a class="sourceLine" id="cb2-18" title="18"><span class="co"># However, if you remove everything, the rebase will be aborted.</span></a>
<a class="sourceLine" id="cb2-19" title="19"><span class="co">#</span></a>
<a class="sourceLine" id="cb2-20" title="20"><span class="co"># Note that empty commits are commented out</span></a></code></pre></div>
<p>This is fine if you’re there to drive an editor for an interactive rebase.</p>
<section id="the-problem-with-interactivity" class="level2">
<h2>The problem with interactivity <a href="https://tylercipriani.com/tags/git/#the-problem-with-interactivity">¶</a></h2>
<p>The problem with interactive rebase is you can’t easily script it.</p>
<p>At work I help to maintain our “beta cluster” which is a bunch of virtual machines that is supposed to mirror the setup of production. The extent to which production is actually mirrored is debatable; however, it is true that we use the same puppet repository as production. Further, this puppet repository resides on a virtual machine within the cluster that acts as the beta cluster’s puppetmaster.</p>
<p>Often, to test a patch for production puppet, folks will apply patches on top of beta’s local copy of the production puppet repo.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" title="1"><span class="ex">root@puppetmaster</span># cd /var/lib/git/operations/puppet</a>
<a class="sourceLine" id="cb3-2" title="2"><span class="ex">root@puppetmaster</span># git apply --check --3way /home/thcipriani/0001-some.patch</a>
<a class="sourceLine" id="cb3-3" title="3"><span class="ex">root@puppetmaster</span># git am --3way /home/thcipriani/0001-some.path</a>
<a class="sourceLine" id="cb3-4" title="4"><span class="ex">root@puppetmaster</span># git status</a>
<a class="sourceLine" id="cb3-5" title="5"><span class="ex">On</span> branch production</a>
<a class="sourceLine" id="cb3-6" title="6"><span class="ex">Your</span> branch is ahead of <span class="st">'origin/production'</span> by 6 commits.</a>
<a class="sourceLine" id="cb3-7" title="7"> <span class="kw">(</span><span class="ex">use</span> <span class="st">"git push"</span> to publish your local commits<span class="kw">)</span></a>
<a class="sourceLine" id="cb3-8" title="8"></a>
<a class="sourceLine" id="cb3-9" title="9"><span class="ex">nothing</span> to commit, working directory clean</a></code></pre></div>
<p>The problem here is that a lot of these commits are old and busted.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb4-1" title="1"><span class="ex">root@puppetmaster</span># git log -6 --format=<span class="st">'%h %ai'</span></a>
<a class="sourceLine" id="cb4-2" title="2"><span class="ex">ad4f419</span> 2016-08-25 20:46:23 +0530</a>
<a class="sourceLine" id="cb4-3" title="3"><span class="ex">d3e9ab8</span> 2016-09-05 15:49:48 +0100</a>
<a class="sourceLine" id="cb4-4" title="4"><span class="ex">59b7377</span> 2016-08-30 16:21:39 -0700</a>
<a class="sourceLine" id="cb4-5" title="5"><span class="ex">5d2609e</span> 2016-08-17 14:17:02 +0100</a>
<a class="sourceLine" id="cb4-6" title="6"><span class="ex">194ee1c</span> 2016-07-19 13:19:54 -0600</a>
<a class="sourceLine" id="cb4-7" title="7"><span class="ex">057c9f7</span> 2016-01-07 17:11:12 -0800</a></code></pre></div>
<p>It’d be nice to have a script that periodically cleans up these patches based on some criteria. This script would have to potentially be able to remove, say, <code>59b7377</code> while leaving all the others in-tact, and it would have to do so without any access to <code>git rebase -i</code> or any user input.</p>
</section>
<section id="non-interactive-commit-deletion" class="level2">
<h2>Non-interactive commit deletion <a href="https://tylercipriani.com/tags/git/#non-interactive-commit-deletion">¶</a></h2>
<p>The way to do this is with <code>git rebase --onto</code>.</p>
<p>Selective quoting of <code>man git-rebase</code></p>
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb5-1" title="1"><span class="ex">SYNOPSIS</span></a>
<a class="sourceLine" id="cb5-2" title="2"> <span class="fu">git</span> rebase [--onto <span class="op"><</span>newbase<span class="op">></span>] [<span class="op"><</span>upstream<span class="op">></span>]</a>
<a class="sourceLine" id="cb5-3" title="3"></a>
<a class="sourceLine" id="cb5-4" title="4"><span class="ex">DESCRIPTION</span></a>
<a class="sourceLine" id="cb5-5" title="5"> <span class="ex">All</span> changes made by commits in the current branch but that are not</a>
<a class="sourceLine" id="cb5-6" title="6"> <span class="kw">in</span> <span class="op"><</span><span class="ex">upstream</span><span class="op">></span> are saved to a temporary area. This is the same set</a>
<a class="sourceLine" id="cb5-7" title="7"> <span class="ex">of</span> commits that would be shown by git log <span class="op"><</span>upstream<span class="op">></span>..HEAD</a>
<a class="sourceLine" id="cb5-8" title="8"></a>
<a class="sourceLine" id="cb5-9" title="9"> <span class="ex">The</span> current branch is reset to <span class="op"><</span>newbase<span class="op">></span> --onto option was supplied.</a>
<a class="sourceLine" id="cb5-10" title="10"></a>
<a class="sourceLine" id="cb5-11" title="11"> <span class="ex">The</span> commits that were previously saved into the temporary area are</a>
<a class="sourceLine" id="cb5-12" title="12"> <span class="kw">then</span> <span class="ex">reapplied</span> to the current branch, one by one, in order.</a></code></pre></div>
<p>The commits we want are all the commits surrounding <code>59b7377</code> without <code>59b7377</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb6-1" title="1"><span class="ex">root@puppetmaster</span># git log --format=<span class="st">'%h %ai'</span> 59b7377..HEAD</a>
<a class="sourceLine" id="cb6-2" title="2"><span class="ex">ad4f419</span> 2016-08-25 20:46:23 +0530</a>
<a class="sourceLine" id="cb6-3" title="3"><span class="ex">d3e9ab8</span> 2016-09-05 15:49:48 +0100</a>
<a class="sourceLine" id="cb6-4" title="4"><span class="ex">root@puppetmaster</span># git log --format=<span class="st">'%h %ai'</span> @<span class="dt">{u}</span>..59b7377^</a>
<a class="sourceLine" id="cb6-5" title="5"><span class="ex">5d2609e</span> 2016-08-17 14:17:02 +0100</a>
<a class="sourceLine" id="cb6-6" title="6"><span class="ex">194ee1c</span> 2016-07-19 13:19:54 -0600</a>
<a class="sourceLine" id="cb6-7" title="7"><span class="ex">057c9f7</span> 2016-01-07 17:11:12 -0800</a></code></pre></div>
<p>So we really want to take the commits <code>59b7377..HEAD</code> and rebase them onto the commit before <code>59b7377</code> (which is <code>59b7377^</code>)</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb7-1" title="1"><span class="ex">root@puppetmaster</span># git rebase --onto 59b7377^ 59b7377</a>
<a class="sourceLine" id="cb7-2" title="2"><span class="ex">root@puppetmaster</span># git log -6 --format=<span class="st">'%h %ai'</span></a>
<a class="sourceLine" id="cb7-3" title="3"><span class="ex">ad4f419</span> 2016-08-25 20:46:23 +0530</a>
<a class="sourceLine" id="cb7-4" title="4"><span class="ex">d3e9ab8</span> 2016-09-05 15:49:48 +0100</a>
<a class="sourceLine" id="cb7-5" title="5"><span class="ex">5d2609e</span> 2016-08-17 14:17:02 +0100</a>
<a class="sourceLine" id="cb7-6" title="6"><span class="ex">194ee1c</span> 2016-07-19 13:19:54 -0600</a>
<a class="sourceLine" id="cb7-7" title="7"><span class="ex">057c9f7</span> 2016-01-07 17:11:12 -0800</a>
<a class="sourceLine" id="cb7-8" title="8"><span class="ex">d5e1340</span> 2016-09-07 23:45:25 +0200</a></code></pre></div>
<p>Tada! Commit gone.</p>
</section>
(ab)Using Git Notes
https://tylercipriani.com/blog/2016/08/26/abusing-git-notes/
Tyler Cipriani
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike License</a>
Copyright © 2017 Tyler Cipriani
2017-07-01T00:49:09Z
2016-08-26T22:35:15Z
<section id="flickr" class="level2">
<h2>Flickr <a href="https://tylercipriani.com/tags/git/#flickr">¶</a></h2>
<p>I like to post my <a href="http://photos.tylercipriani.com/">photos on the internet</a>. I used to post all of my photos on <a href="https://www.flickr.com/photos/tylercipriani/">Flickr</a>, but that site has been getting <a href="https://github.com/thcipriani/dotfiles/commit/c2ff9eeedb1c6634982efc940e43335264018269">worse</a> and <a href="https://techcrunch.com/2013/05/20/flickr-gets-a-huge-revamp-with-hi-res-image-filled-ui-new-android-app-and-1tb-of-free-storage/">worse</a> and <a href="https://www.theguardian.com/technology/2016/jul/25/yahoo-moves-next-for-flickr">worse</a>. More recently, I’ve been using a static photo gallery generator I <strike>wrote</strike> hacked together that I (perhaps unfortunately) named <a href="https://github.com/thcipriani/dotfiles/tree/master/bin/hiraeth">hiraeth</a>.</p>
<p>Hiraeth is, to put it mildly, missing some features. There are a few reasons that I opted to create hiraeth rather than use something that was already built:</p>
<ol type="1">
<li>I <em>need</em> to host my own photos now, evidently. The internet has seemingly decided to sell its user-base to the highest bidder, so hosted services are out.</li>
<li>I think it makes sense to host my photos statically, since they’re static (mostly).</li>
<li>I really <em>like</em> the way my <code>~/Pictures</code> directory is organized—I can find stuff—and I don’t want to mess all that up to generate a crappy website out of my photos.</li>
<li>I use git-annex to manage my <code>~/Pictures</code>, which creates…unique challenges :)</li>
</ol>
<p>Hiraeth is invoked like: <code>publish [edited-photo-dir] [output-dir]</code>. Hiraeth looks for a file named <code>_metadata.yaml</code> inside the directory of edited photos and uses that to map photo files to photo descriptions and add titles and whatnot to the page. It makes a few different sized thumbnails of each photo, grabs the exif info, and generates some html.</p>
<p>Hiraeth was designed to look and behave like a static version of Flickr circa 2007. There are still features to add, but there is a base that works in place at least.</p>
</section>
<section id="home-pictures" class="level2">
<h2>Home Pictures <a href="https://tylercipriani.com/tags/git/#home-pictures">¶</a></h2>
<p>I mange my <code>~/Pictures</code> directory using <a href="https://git-annex.branchable.com/">git-annex</a> (which I’ve wanted to write something about for a long time). This is mostly amazing and great. Git-annex has a lot of cool features. For instance, in git-annex once you’ve copied files to a remote, it will allow you to “<code>drop</code>” a file locally to save space. You can still get the file back from the remote any time you rootin’ tootin’ feel like, so nbd. Occasionally, when I’m running out of space on one machine or another, I’ll <code>drop</code> a bunch of photos.</p>
<p>The ability to drop a bunch of photos means that hiraeth needs to be able to get photo metadata from a picture without having the file <em>actually</em> be on disk.</p>
</section>
<section id="gerrit" class="level2">
<h2>Gerrit <a href="https://tylercipriani.com/tags/git/#gerrit">¶</a></h2>
<p>We use gerrit at work and I genuinely like it.</p>
<p><code><rant></code> The web-UI is one of the worst interfaces I’ve ever used. The web interface is an unfortunate mix of late-90s, designed-by-engineers, impossibly-option-filled interface mashed together in an unholy union with a fancy-schmancy new-fangled javascripty single-page application. It’s basically a mix of two interface paradigms I hate, yet rarely see in concert: back-button breakage + no design aesthetic whatsoever. <code></rant></code></p>
<p><strong>HOWEVER</strong>, The workflow gerrit enforces, the git features it uses, and the beautiful repository history that results makes gerrit a really nice code review system.</p>
<p>Gerrit is the first system I’ve seen use git-notes.</p>
<p>Gerrit has a cool feature where it keeps all of the patch review in git-notes:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="ex">tyler@taskmaster</span>:mediawiki-core$ git fetch origin refs/notes/*:refs/notes/*</a>
<a class="sourceLine" id="cb1-2" title="2"><span class="ex">remote</span>: Counting objects: 176401, done</a>
<a class="sourceLine" id="cb1-3" title="3"><span class="ex">remote</span>: Finding sources: 100% (147886/147886)</a>
<a class="sourceLine" id="cb1-4" title="4"><span class="ex">remote</span>: Getting sizes: 100% (1723/1723)</a>
<a class="sourceLine" id="cb1-5" title="5"><span class="ex">remote</span>: Compressing objects: 100% (116810/116810)</a>
<a class="sourceLine" id="cb1-6" title="6"><span class="ex">remote</span>: Total 147886 (delta 120436), <span class="ex">reused</span> 147854 (delta 120434)</a>
<a class="sourceLine" id="cb1-7" title="7"><span class="ex">Receiving</span> objects: 100% (147886/147886), <span class="ex">14.91</span> MiB <span class="kw">|</span> <span class="ex">3.01</span> MiB/s, done.</a>
<a class="sourceLine" id="cb1-8" title="8"><span class="ex">Resolving</span> deltas: 100% (120449/120449), <span class="kw">done</span><span class="ex">.</span></a>
<a class="sourceLine" id="cb1-9" title="9"><span class="ex">From</span> ssh://gerrit.wikimedia.org:29418/mediawiki/core</a>
<a class="sourceLine" id="cb1-10" title="10"> <span class="ex">*</span> [new ref] refs/notes/commits -<span class="op">></span> refs/notes/commits</a>
<a class="sourceLine" id="cb1-11" title="11"> <span class="ex">*</span> [new ref] refs/notes/review -<span class="op">></span> refs/notes/review</a>
<a class="sourceLine" id="cb1-12" title="12"><span class="ex">tyler@taskmaster</span>:mediawiki-core$ ls -l .git/refs/notes</a>
<a class="sourceLine" id="cb1-13" title="13"><span class="ex">total</span> 8</a>
<a class="sourceLine" id="cb1-14" title="14"><span class="ex">-rw-r--r--</span> 1 tyler tyler 41 Aug 28 16:44 commits</a>
<a class="sourceLine" id="cb1-15" title="15"><span class="ex">-rw-r--r--</span> 1 tyler tyler 41 Aug 28 16:44 review</a>
<a class="sourceLine" id="cb1-16" title="16"><span class="ex">tyler@taskmaster</span>:mediawiki-core$ git log --show-notes=review --author=<span class="st">'Tyler Cipriani'</span></a>
<a class="sourceLine" id="cb1-17" title="17"> <span class="ex">commit</span> ab131d4be475bf87b0f0a86fa356a2b1a188a673</a>
<a class="sourceLine" id="cb1-18" title="18"> <span class="ex">Author</span>: Tyler Cipriani <span class="op"><</span>tcipriani@wikimedia.org<span class="op">></span></a>
<a class="sourceLine" id="cb1-19" title="19"> <span class="ex">Date</span>: Tue Mar 22 09:08:52 2016 -0700</a>
<a class="sourceLine" id="cb1-20" title="20"> </a>
<a class="sourceLine" id="cb1-21" title="21"> <span class="ex">Revert</span> <span class="st">"Add link to anon's user page; remove "</span>Not logged in<span class="st">""</span></a>
<a class="sourceLine" id="cb1-22" title="22"> </a>
<a class="sourceLine" id="cb1-23" title="23"> <span class="ex">This</span> reverts change I049d0671a7050.</a>
<a class="sourceLine" id="cb1-24" title="24"> </a>
<a class="sourceLine" id="cb1-25" title="25"> <span class="ex">This</span> change was reverted in the wmf/1.27.0-wmf.17. Since there is no</a>
<a class="sourceLine" id="cb1-26" title="26"> <span class="fu">clear</span> consensus, revert in master before branching wmf/1.27.0-wmf.18.</a>
<a class="sourceLine" id="cb1-27" title="27"> <span class="ex">Bug</span>: T121793</a>
<a class="sourceLine" id="cb1-28" title="28"> <span class="ex">Change-Id</span>: I2dc0f2562c908d4e419d34e80a64065843778f3d</a>
<a class="sourceLine" id="cb1-29" title="29"> </a>
<a class="sourceLine" id="cb1-30" title="30"> <span class="ex">Notes</span> (review)<span class="bu">:</span></a>
<a class="sourceLine" id="cb1-31" title="31"> <span class="ex">Verified+2</span>: jenkins-bot</a>
<a class="sourceLine" id="cb1-32" title="32"> <span class="ex">Code-Review+2</span>: Legoktm <span class="op"><</span>legoktm.wikipedia@gmail.com<span class="op">></span></a>
<a class="sourceLine" id="cb1-33" title="33"> <span class="ex">Submitted-by</span>: jenkins-bot</a>
<a class="sourceLine" id="cb1-34" title="34"> <span class="ex">Submitted-at</span>: Tue, 22 Mar 2016 18:08:27 +0000</a>
<a class="sourceLine" id="cb1-35" title="35"> <span class="ex">Reviewed-on</span>: https://gerrit.wikimedia.org/r/278923</a>
<a class="sourceLine" id="cb1-36" title="36"> <span class="ex">Project</span>: mediawiki/core</a>
<a class="sourceLine" id="cb1-37" title="37"> <span class="ex">Branch</span>: refs/heads/master</a></code></pre></div>
<p>This is super cool. You can have, effectively, an offline backup of lots of information you’d usually have to brave the gerrit web-ui to find. Plus, you don’t <em>have to</em> have this information in your local repo taking up space, it’s only there if you fetch it down.</p>
<p>There is another project from Google that uses git-notes for review called <a href="https://github.com/google/git-appraise">git-appraise</a>.</p>
<p>This is the stated use of git-notes in the docs: store extra information about a commit, without changing the SHA1 of the commit by modifying its contents.</p>
<p>It is, however, noteworthy that you can store a note that points to any object in your repository and not just commit objects.</p>
</section>
<section id="exif-data-without-pictures" class="level2">
<h2>EXIF data without pictures <a href="https://tylercipriani.com/tags/git/#exif-data-without-pictures">¶</a></h2>
<p>After some minor testing it seems that I can store all the EXIF info I need about my images in git-notes without <em>actually</em> having those images on disk; i.e., I can have git-annex drop the actual files and just have broken symlinks that point to where the files live in annex.</p>
<p>I wrote a <a href="https://gist.github.com/thcipriani/e56cdef56a98eb0cf7e93dadf94fbdd8">small bash script</a> to play with some of these ideas.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="ex">tyler@taskmaster</span>:Pictures$ git photo show fish.jpg</a>
<a class="sourceLine" id="cb2-2" title="2"><span class="ex">+</span> git notes --ref=pictures show d4a9c57715ce63a228577900d1abc027</a>
<a class="sourceLine" id="cb2-3" title="3"><span class="ex">error</span>: No note found for object d4a9c57715ce63a228577900d1abc0273396e8ef.</a>
<a class="sourceLine" id="cb2-4" title="4"><span class="ex">tyler@taskmaster</span>:Pictures$ git photo add fish.jpg</a>
<a class="sourceLine" id="cb2-5" title="5"><span class="ex">+</span> git notes --ref=pictures add -m <span class="st">'FileName: fish.jpg</span></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="st">FileTypeExtension: jpg</span></a>
<a class="sourceLine" id="cb2-7" title="7"><span class="st">Make: NIKON CORPORATION</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="st">Model: NIKON D610</span></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="st">LensID: AF-S Zoom-Nikkor 24-70mm f/2.8G ED</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="st">FocalLength: 62.0 mm</span></a>
<a class="sourceLine" id="cb2-11" title="11"><span class="st">FNumber: 2.8</span></a>
<a class="sourceLine" id="cb2-12" title="12"><span class="st">ISO: 3200'</span> d4a9c57715ce63a228577900d1abc027</a>
<a class="sourceLine" id="cb2-13" title="13"><span class="ex">+</span> set +x</a>
<a class="sourceLine" id="cb2-14" title="14"><span class="ex">tyler@taskmaster</span>:Pictures$ git photo show fish.jpg</a>
<a class="sourceLine" id="cb2-15" title="15"><span class="ex">+</span> git notes --ref=pictures show d4a9c57715ce63a228577900d1abc027</a>
<a class="sourceLine" id="cb2-16" title="16"><span class="ex">FileName</span>: fish.jpg</a>
<a class="sourceLine" id="cb2-17" title="17"><span class="ex">FileTypeExtension</span>: jpg</a>
<a class="sourceLine" id="cb2-18" title="18"><span class="ex">Make</span>: NIKON CORPORATION</a>
<a class="sourceLine" id="cb2-19" title="19"><span class="ex">Model</span>: NIKON D610</a>
<a class="sourceLine" id="cb2-20" title="20"><span class="ex">LensID</span>: AF-S Zoom-Nikkor 24-70mm f/2.8G ED</a>
<a class="sourceLine" id="cb2-21" title="21"><span class="ex">FocalLength</span>: 62.0 mm</a>
<a class="sourceLine" id="cb2-22" title="22"><span class="ex">FNumber</span>: 2.8</a>
<a class="sourceLine" id="cb2-23" title="23"><span class="ex">ISO</span>: 3200</a>
<a class="sourceLine" id="cb2-24" title="24"><span class="ex">+</span> set +x</a></code></pre></div>
<p>Now it seems like it <em>should be</em> possible to <code>git push origin refs/notes/pictures</code>, fetch them on the other side, and modify hiraeth to read EXIF from notes when the symlink target doesn’t exist.</p>
<p>We’ll see how any of that goes in practice :<br />
</p>
</section>
Git annex notes
https://tylercipriani.com/blog/2015/05/13/git-annex/
Tyler Cipriani
Creative Commons Attribution-ShareAlike License
Copyright © 2017 Tyler Cipriani
2017-02-14T15:11:05Z
2015-05-13T22:29:34Z
<section id="setup-new-repo" class="level2">
<h2>Setup New repo <a href="https://tylercipriani.com/tags/git/#setup-new-repo">¶</a></h2>
<ol>
<li><p>init git:</p>
<div class="sourceCode" id="cb1" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="fu">git</span> init</a></code></pre></div></li>
<li><p>init git annex:</p>
<div class="sourceCode" id="cb2" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="fu">git</span> annex init local</a></code></pre></div></li>
<li><p>Add S3 Remote named public-s3</p>
<div class="sourceCode" id="cb3" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" title="1"><span class="fu">git</span> annex initremote public-s3 type=S3 encryption=none bucket=tyler.zone chunk=0</a></code></pre></div></li>
<li><p>Add file to git annex</p>
<div class="sourceCode" id="cb4" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb4-1" title="1"><span class="fu">git</span> annex add [big-file]</a></code></pre></div></li>
<li><p>copy current directory to public-s3 remote</p>
<div class="sourceCode" id="cb5" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb5-1" title="1"><span class="fu">git</span> annex copy --to public-s3</a></code></pre></div></li>
<li><p>remove local copy—will only remove if already in remote—nothing lost</p>
<div class="sourceCode" id="cb6" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb6-1" title="1"><span class="fu">git</span> annex drop [file]</a></code></pre></div></li>
<li><p>Commit</p>
<div class="sourceCode" id="cb7" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb7-1" title="1"><span class="fu">git</span> -a -m <span class="st">'initial commit'</span></a></code></pre></div></li>
</ol>
</section>
<section id="setup-nfs-as-remote-using-rsync-over-ssh" class="level2">
<h2>Setup NFS as remote using Rsync over ssh <a href="https://tylercipriani.com/tags/git/#setup-nfs-as-remote-using-rsync-over-ssh">¶</a></h2>
<ol>
<li><p><a href="https://git-annex.branchable.com/special_remotes/rsync/">Add Rsync as unencrypted remote</a></p>
<div class="sourceCode" id="cb8" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb8-1" title="1"><span class="fu">git</span> annex initremote nas type=rsync rsyncurl=nfs.blazeyandltyler.com:/volume1/homes/tyler/PicturesAnnex encryption=none</a></code></pre></div></li>
<li><p>Add file to nas</p>
<div class="sourceCode" id="cb9" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb9-1" title="1"><span class="fu">git</span> annex copy --to=nas</a></code></pre></div></li>
</ol>
</section>
<section id="pull-down-photos" class="level2">
<h2>Pull down photos <a href="https://tylercipriani.com/tags/git/#pull-down-photos">¶</a></h2>
<div class="sourceCode" id="cb10" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb10-1" title="1"><span class="bu">eval</span> (~/.amazonrc)</a>
<a class="sourceLine" id="cb10-2" title="2"><span class="fu">git</span> annex enableremote public-s3</a>
<a class="sourceLine" id="cb10-3" title="3"><span class="fu">git</span> annex get [whatever]</a></code></pre></div>
</section>
<section id="make-available-to-the-public-after-public-s3-setup" class="level2">
<h2>Make available to the public (after public s3 setup): <a href="https://tylercipriani.com/tags/git/#make-available-to-the-public-after-public-s3-setup">¶</a></h2>
<div class="sourceCode" id="cb11" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb11-1" title="1"><span class="fu">git</span> annex addurl --file [filename] <span class="st">"http://tyler.zone/</span><span class="va">$(</span><span class="fu">git</span> annex lookupkey [filename]<span class="va">)</span><span class="st">"</span></a></code></pre></div>
</section>
<section id="list-remotes-and-remote-info" class="level2">
<h2>List remotes and remote info <a href="https://tylercipriani.com/tags/git/#list-remotes-and-remote-info">¶</a></h2>
</section>
<section id="show-remotes" class="level2">
<h2>Show remotes <a href="https://tylercipriani.com/tags/git/#show-remotes">¶</a></h2>
<div class="sourceCode" id="cb12" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb12-1" title="1"><span class="fu">git</span> annex enableremote</a></code></pre></div>
</section>
<section id="show-remote-info" class="level2">
<h2>Show remote info <a href="https://tylercipriani.com/tags/git/#show-remote-info">¶</a></h2>
<div class="sourceCode" id="cb13" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb13-1" title="1"><span class="fu">git</span> annex info [remote-name]</a>
<a class="sourceLine" id="cb13-2" title="2"><span class="fu">git</span> annex info tylercipriani-raw</a></code></pre></div>
</section>
<section id="finding-info-about-files" class="level2">
<h2>Finding info about files <a href="https://tylercipriani.com/tags/git/#finding-info-about-files">¶</a></h2>
<p>Find a file:</p>
<div class="sourceCode" id="cb14" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb14-1" title="1"><span class="fu">git</span> annex whereis [filename]</a></code></pre></div>
<p>Adding a file to <a href="http://tyler.zone">http://tyler.zone</a></p>
<div class="sourceCode" id="cb15" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb15-1" title="1"><span class="bu">eval</span> <span class="va">$(</span><span class="ex">~/.amazonrc</span><span class="va">)</span></a>
<a class="sourceLine" id="cb15-2" title="2"><span class="fu">git</span> annex copy --to=photo-site [file]</a>
<a class="sourceLine" id="cb15-3" title="3"><span class="fu">git</span> annex addurl --file [file] <span class="st">"http://tyler.zone/</span><span class="va">$(</span><span class="fu">git</span> annex lookupkey [filename]<span class="va">)</span><span class="st">"</span></a></code></pre></div>
</section>
<section id="sharing-via-amazon-s3" class="level2">
<h2>Sharing via Amazon s3 <a href="https://tylercipriani.com/tags/git/#sharing-via-amazon-s3">¶</a></h2>
</section>
<section id="links" class="level2">
<h2>Links <a href="https://tylercipriani.com/tags/git/#links">¶</a></h2>
<ul>
<li><a href="http://git-annex.branchable.com/tips/publishing_your_files_to_the_public/">http://git-annex.branchable.com/tips/publishing_your_files_to_the_public/</a></li>
<li><a href="http://git-annex.branchable.com/tips/using_Amazon_S3/">http://git-annex.branchable.com/tips/using_Amazon_S3/</a></li>
</ul>
</section>
<section id="setup" class="level2">
<h2>Setup <a href="https://tylercipriani.com/tags/git/#setup">¶</a></h2>
<p>Make amazon bucket with policy:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode json"><code class="sourceCode json"><a class="sourceLine" id="cb16-1" title="1"><span class="fu">{</span></a>
<a class="sourceLine" id="cb16-2" title="2"> <span class="dt">"Version"</span><span class="fu">:</span> <span class="st">"2008-10-17"</span><span class="fu">,</span></a>
<a class="sourceLine" id="cb16-3" title="3"> <span class="dt">"Statement"</span><span class="fu">:</span> <span class="ot">[</span></a>
<a class="sourceLine" id="cb16-4" title="4"> <span class="fu">{</span></a>
<a class="sourceLine" id="cb16-5" title="5"> <span class="dt">"Sid"</span><span class="fu">:</span> <span class="st">"AllowPublicRead"</span><span class="fu">,</span></a>
<a class="sourceLine" id="cb16-6" title="6"> <span class="dt">"Effect"</span><span class="fu">:</span> <span class="st">"Allow"</span><span class="fu">,</span></a>
<a class="sourceLine" id="cb16-7" title="7"> <span class="dt">"Principal"</span><span class="fu">:</span> <span class="fu">{</span></a>
<a class="sourceLine" id="cb16-8" title="8"> <span class="dt">"AWS"</span><span class="fu">:</span> <span class="st">"*"</span></a>
<a class="sourceLine" id="cb16-9" title="9"> <span class="fu">},</span></a>
<a class="sourceLine" id="cb16-10" title="10"> <span class="dt">"Action"</span><span class="fu">:</span> <span class="st">"s3:GetObject"</span><span class="fu">,</span></a>
<a class="sourceLine" id="cb16-11" title="11"> <span class="dt">"Resource"</span><span class="fu">:</span> <span class="st">"arn:aws:s3:::[bucket-name]/*"</span></a>
<a class="sourceLine" id="cb16-12" title="12"> <span class="fu">}</span></a>
<a class="sourceLine" id="cb16-13" title="13"> <span class="ot">]</span></a>
<a class="sourceLine" id="cb16-14" title="14"><span class="fu">}</span></a></code></pre></div>
<p>Put creds out into the environment</p>
<div class="sourceCode" id="cb17" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb17-1" title="1"><span class="bu">eval</span> (~/.amazonrc)</a>
<a class="sourceLine" id="cb17-2" title="2"><span class="bu">cd</span> into repo:</a>
<a class="sourceLine" id="cb17-3" title="3"><span class="bu">cd</span> /home/tyler/Projects/Timelapse</a></code></pre></div>
</section>