diff options
Diffstat (limited to '.html/git')
| -rw-r--r-- | .html/git/_list.html | 109 | ||||
| -rw-r--r-- | .html/git/config.html | 151 | ||||
| -rw-r--r-- | .html/git/detached-sigs.html | 359 | ||||
| -rw-r--r-- | .html/git/index.html | 109 | ||||
| -rw-r--r-- | .html/git/integrate.html | 118 | ||||
| -rw-r--r-- | .html/git/pull-request-workflow.html | 163 | ||||
| -rw-r--r-- | .html/git/scratch.html | 134 | ||||
| -rw-r--r-- | .html/git/stop-using-git-pull-to-deploy.html | 178 | ||||
| -rw-r--r-- | .html/git/survival.html | 174 | ||||
| -rw-r--r-- | .html/git/theory-and-practice/_list.html | 96 | ||||
| -rw-r--r-- | .html/git/theory-and-practice/index.html | 126 | ||||
| -rw-r--r-- | .html/git/theory-and-practice/objects.html | 202 | ||||
| -rw-r--r-- | .html/git/theory-and-practice/refs-and-names.html | 199 |
13 files changed, 2118 insertions, 0 deletions
diff --git a/.html/git/_list.html b/.html/git/_list.html new file mode 100644 index 0000000..59ee1d4 --- /dev/null +++ b/.html/git/_list.html @@ -0,0 +1,109 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + ls /git + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + <span class="list-crumb">list</span> + + </li> + + </ol> + + + + <div id="listing"> + <h1><code>ls /git</code></h1> + + + <div id="directories"> + <h2>Directories</h2> + <ul> + + <li><a href="theory-and-practice/">theory-and-practice/</a></li> + + </ul> + </div> + + + + <div id="pages"> + <h2>Pages</h2> + <ul> + + <li><a href="scratch">Git Is Not Magic</a></li> + + <li><a href="survival">Git Survival Guide</a></li> + + <li><a href="integrate">Integrating with Git: A Field Guide</a></li> + + <li><a href="pull-request-workflow">Life With Pull Requests</a></li> + + <li><a href="detached-sigs">Notes Towards Detached Signatures in Git</a></li> + + <li><a href="stop-using-git-pull-to-deploy">Stop Using Git Pull To Deploy</a></li> + + <li><a href="config">git-config Settings You Want</a></li> + + </ul> + </div> + + + + </div> + + + + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git">See this directory on Bitbucket</a>. + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/config.html b/.html/git/config.html new file mode 100644 index 0000000..c21c4f5 --- /dev/null +++ b/.html/git/config.html @@ -0,0 +1,151 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + git-config Settings You Want + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + config + + </li> + + </ol> + + + + <div id="article"> + <h1 id="git-config-settings-you-want">git-config Settings You Want</h1> +<p>Git comes with some fairly <a href="http://www.tux.org/lkml/">lkml</a>-specific +configuration defaults. You should fix this. All of the items below can be set +either for your entire login account (<code>git config --global</code>) or for a specific +repository (<code>git config</code>).</p> +<p>Full documentation is under <code>git help config</code>, unless otherwise stated.</p> +<ul> +<li> +<p><code>git config user.name 'Your Full Name'</code> and <code>git config user.email + 'your-email@example.com'</code>, obviously.</p> +</li> +<li> +<p><code>git config push.default simple</code> - the default behaviour (called <code>matching</code>) + of an unqualified <code>git push</code> is to identify pairs of branches by name and + push all matches from your local repository to the remote. Given that + branches have explicit “upstream” configuration identifying which, if any, + branch in which, if any, remote they're associated with, this is dumb. The + <code>simple</code> mode pushes the current branch to its upstream remote, if and only + if the local branch name and the remote branch name match <em>and</em> the local + branch tracks the remote branch. Requires Git 1.8 or later; will be the + default in Git 2.0. (For older versions of Git, use <code>upstream</code> instead, + which does not require that branch names match.)</p> +</li> +<li> +<p><code>git config merge.defaultToUpstream true</code> - causes an unqualified <code>git + merge</code> to merge the current branch's configured upstream branch, rather than + being an error. (<code>git rebase</code> always has this behaviour. Consistent!) You + should still merge thoughtfully.</p> +</li> +<li> +<p><code>git config rebase.autosquash true</code> - causes <code>git rebase -i</code> to parse magic + comments created by <code>git commit --squash=some-hash</code> and <code>git commit + --fixup=some-hash</code> and reorder the commit list before presenting it for + further editing. See the descriptions of “squash” and “fixup” in <code>git help + rebase</code> for details; autosquash makes amending commits other than the most + recent easier and less error-prone.</p> +</li> +<li> +<p><code>git config branch.autosetupmerge always</code> - newly-created branches whose + start point is a branch (<code>git checkout master -b some-feature</code>, <code>git branch + some-feature origin/develop</code>, and so on) will be configured to have the + start point branch as their upstream. By default (with <code>true</code> rather than + <code>always</code>) this only happens when the start point is a remote-tracking + branch.</p> +</li> +<li> +<p><code>git config rerere.enabled true</code> - enable “reuse recorded resolution.” The + <code>git help rerere</code> docs explain it pretty well, but the short version is that + git can record how you resolve conflicts during a “test” merge and reuse the + same approach when resolving the same conflict later, in a “real” merge.</p> +</li> +</ul> +<h2 id="for-advanced-users">For advanced users</h2> +<p>A few things are nice when you're getting started, but become annoying when +you no longer need them.</p> +<ul> +<li><code>git config advice.detachedHead</code> - if you already understand the difference + between having a branch checked out and having a commit checked out, and + already understand what “detatched head” means, the warning on every <code>git + checkout ...some detatched thing...</code> isn't helping anyone. This is also + useful repositories used for deployment, where specific commits (from tags, + for example) are regularly checked out.</li> +</ul> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/config.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/config.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/detached-sigs.html b/.html/git/detached-sigs.html new file mode 100644 index 0000000..a3e439d --- /dev/null +++ b/.html/git/detached-sigs.html @@ -0,0 +1,359 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Notes Towards Detached Signatures in Git + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + detached-sigs + + </li> + + </ol> + + + + <div id="article"> + <h1 id="notes-towards-detached-signatures-in-git">Notes Towards Detached Signatures in Git</h1> +<p>Git supports a limited form of object authentication: specific object +categories in Git's internal model can have <a href="../gpg/terrible">GPG</a> signatures +embedded in them, allowing the authorship of the objects to be verified using +<a href="../gpg/cool">GPG</a>'s underlying trust model. Tag signatures can be used to +verify the authenticity and integrity of the <em>snapshot associated with a +tag</em>, and the authenticity of the tag itself, filling a niche broadly similar +to code signing in binary distribution systems. Commit signatures can be used +to verify the authenticity of the <em>snapshot associated with the commit</em>, and +the authorship of the commit itself. (Conventionally, commit signatures are +assumed to also authenticate either the entire line of history leading to a +commit, or the diff between the commit and its first parent, or both.)</p> +<p>Git's existing system has some tradeoffs.</p> +<ul> +<li> +<p>Signatures are embedded within the objects they sign. The signature is part + of the object's identity; since Git is content-addressed, this means that + an object can neither be retroactively signed nor retroactively stripped of + its signature without modifying the object's identity. Git's distributed + model means that these sorts of identity changes are both complicated and + easily detected.</p> +</li> +<li> +<p>Commit signatures are second-class citizens. They're a relatively recent + addition to the Git suite, and both the implementation and the social + conventions around them continue to evolve.</p> +</li> +<li> +<p>Only some objects can be signed. While Git has relatively weak rules about + workflow, the signature system assumes you're using one of Git's more + widespread workflows by limiting your options to at most one signature, and + by restricting signatures to tags and commits (leaving out blobs, trees, + and refs).</p> +</li> +</ul> +<p>I believe it would be useful from an authentication standpoint to add +"detached" signatures to Git, to allow users to make these tradeoffs +differently if desired. These signatures would be stored as separate (blob) +objects in a dedicated <code>refs</code> namespace, supporting retroactive signatures, +multiple signatures for a given object, "policy" signatures, and +authentication of arbitrary objects.</p> +<p>The following notes are partially guided by Git's one existing "detached +metadata" facility, <code>git notes</code>. Similarities are intentional; divergences +will be noted where appropriate. Detached signatures are meant to +interoperate with existing Git workflow as much as possible: in particular, +they can be fetched and pushed like any other bit of Git metadata.</p> +<p>A detached signature cryptographically binds three facts together into an +assertion whose authenticity can be checked by anyone with access to the +signatory's keys:</p> +<ol> +<li>An object (in the Git sense; a commit, tag, tree, or blob),</li> +<li>A policy label, and</li> +<li>A signatory (a person or agent making the assertion).</li> +</ol> +<p>These assertions can be published separately from or in tandem with the +objects they apply to.</p> +<h2 id="policies">Policies</h2> +<p>Taking a hint from Monotone, every signature includes a "policy" identifying +how the signature is meant to be interpreted. Policies are arbitrary strings; +their meaning is entirely defined by tooling and convention, not by this +draft.</p> +<p>This draft uses a single policy, <code>author</code>, for its examples. A signature +under the <code>author</code> policy implies that the signatory had a hand in the +authorship of the designated object. (This is compatible with existing +interpretations of signed tags and commits.) (Authorship under this model is +strictly self-attested: you can claim authorship of anything, and you cannot +assert anyone else's authorship.)</p> +<p>The Monotone documentation suggests a number of other useful policies related +to testing and release status, automated build results, and numerous other +factors. Use your imagination.</p> +<h2 id="whats-in-a-signature">What's In A Signature</h2> +<p>Detached signatures cover the disk representation of an object, as given by</p> +<pre><code>git cat-file <TYPE> <SHA1> +</code></pre> +<p>For most of Git's object types, this means that the signed content is plain +text. For <code>tree</code> objects, the signed content is the awful binary +representation of the tree, <em>not</em> the pretty representation given by <code>git +ls-tree</code> or <code>git show</code>.</p> +<p>Detached signatures include the "policy" identifier in the signed content, to +prevent others from tampering with policy choices via <code>refs</code> hackery. (This +will make more sense momentarily.) The policy identifier is prepended to the +signed content, terminated by a zero byte (as with Git's own type +identifiers, but without a length field as length checks are performed by +signing and again when the signature is stored in Git).</p> +<p>To generate the <em>complete</em> signable version of an object, use something +equivalent to the following shell snippet:</p> +<pre><code># generate-signable POLICY TYPE SHA1 +function generate-signable() { + echo -n "$1" + SOMETHING OUTPUTTING A NUL HERE + git cat-file "$2" "$3" +} +</code></pre> +<p>(In the process of writing this, I discovered how hard it is to get Unix's +C-derived shell tools to emit a zero byte.)</p> +<h2 id="signature-storage-and-naming">Signature Storage and Naming</h2> +<p>We assume that a userid will sign an object at most once.</p> +<p>Each signature is stored in an independent blob object in the repository it +applies to. The signature object (described above) is stored in Git, and its +hash recorded in <code>refs/signatures/<POLICY>/<SUBJECT SHA1>/<SIGNER KEY +FINGERPRINT></code>.</p> +<pre><code># sign POLICY TYPE SHA1 FINGERPRINT +function sign() { + local SIG_HASH=$( + generate-signable "$@" | + gpg --batch --no-tty --sign -u "$4" | + git hash-object --stdin -w -t blob + ) + git update-ref "refs/signatures/$1/$3/$4" +} +</code></pre> +<p>Stored signatures always use the complete fingerprint to identify keys, to +minimize the risk of colliding key IDs while avoiding the need to store full +keys in the <code>refs</code> naming hierarchy.</p> +<p>The policy name can be reliably extracted from the ref, as the trailing part +has a fixed length (in both path segments and bytes) and each ref begins with +a fixed, constant prefix <code>refs/signatures/</code>.</p> +<h2 id="signature-verification">Signature Verification</h2> +<p>Given a signature ref as described above, we can verify and authenticate the +signature and bind it to the associated object and policy by performing the +following check:</p> +<ol> +<li>Pick apart the ref into policy, SHA1, and key fingerprint parts.</li> +<li>Reconstruct the signed body as above, using the policy name extracted from + the ref.</li> +<li>Retrieve the signature from the ref and combine it with the object itself.</li> +<li>Verify that the policy in the stored signature matches the policy in the + ref.</li> +<li> +<p>Verify the signature with GPG:</p> +<pre><code># verify-gpg POLICY TYPE SHA1 FINGERPRINT +verify-gpg() { + { + git cat-file "$2" "$3" + git cat-file "refs/signatures/$1/$3/$4" + } | gpg --batch --no-tty --verify +} +</code></pre> +</li> +<li> +<p>Verify the key fingerprint of the signing key matches the key fingerprint + in the ref itself.</p> +</li> +</ol> +<p>The specific rules for verifying the signature in GPG are left up to the user +to define; for example, some sites may want to auto-retrieve keys and use a +web of trust from some known roots to determine which keys are trusted, while +others may wish to maintain a specific, known keyring containing all signing +keys for each policy, and skip the web of trust entirely. This can be +accomplished via <code>git-config</code>, given some work, and via <code>gpg.conf</code>.</p> +<h2 id="distributing-signatures">Distributing Signatures</h2> +<p>Since each signature is stored in a separate ref, and since signatures are +<em>not</em> expected to be amended once published, the following refspec can be +used with <code>git fetch</code> and <code>git push</code> to distribute signatures:</p> +<pre><code>refs/signatures/*:refs/signatures/* +</code></pre> +<p>Note the lack of a <code>+</code> decoration; we explicitly do not want to auto-replace +modified signatures, normally; explicit user action should be required.</p> +<h2 id="workflow-notes">Workflow Notes</h2> +<p>There are two verification workflows for signatures: "static" verification, +where the repository itself already contains all the refs and objects needed +for signature verification, and "pre-receive" verification, where an object +and its associated signature may be being uploaded at the same time.</p> +<p><em>It is impractical to verify signatures on the fly from an <code>update</code> hook</em>. +Only <code>pre-receive</code> hooks can usefully accept or reject ref changes depending +on whether the push contains a signature for the pushed objects. (Git does +not provide a good mechanism for ensuring that signature objects are pushed +before their subjects.) Correctly verifying object signatures during +<code>pre-receive</code> regardless of ref order is far too complicated to summarize +here.</p> +<h2 id="attacks">Attacks</h2> +<h3 id="lies-of-omission">Lies of Omission</h3> +<p>It's trivial to hide signatures by deleting the signature refs. Similarly, +anyone with access to a repository can delete any or all detached signatures +from it without otherwise invalidating the signed objects.</p> +<p>Since signatures are mostly static, sites following the recommended no-force +policy for signature publication should only be affected if relatively recent +signatures are deleted. Older signatures should be available in one or more +of the repository users' loca repositories; once created, a signature can be +legitimately obtained from anywhere, not only from the original signatory.</p> +<p>The signature naming protocol is designed to resist most other forms of +assertion tampering, but straight-up omission is hard to prevent.</p> +<h3 id="unwarranted-certification">Unwarranted Certification</h3> +<p>The <code>policy</code> system allows any signatory to assert any policy. While +centralized signature distribution points such as "release" repositories can +make meaningful decisions about which signatures they choose to accept, +publish, and propagate, there's no way to determine after the fact whether a +policy assertion was obtained from a legitimate source or a malicious one +with no grounds for asserting the policy.</p> +<p>For example, I could, right now, sign an <code>all-tests-pass</code> policy assertion +for the Linux kernel. While there's no chance on Earth that the LKML team +would propagate that assertion, if I can convince you to fetch signatures +from my repository, you will fetch my bogus assertion. If <code>all-tests-pass</code> is +a meaningful policy assertion for the Linux kernel, then you will have very +few options besides believing that I assert that all tests have passed.</p> +<h3 id="ambigiuous-policy">Ambigiuous Policy</h3> +<p>This is an ongoing problem with crypto policy systems and user interfaces +generally, but this design does <em>nothing</em> to ensure that policies are +interpreted uniformly by all participants in a repository. In particular, +there's no mechanism described for distributing either prose or programmatic +policy definitions and checks. All policy information is out of band.</p> +<p>Git already has ambiguity problems around commit signing: there are multiple +ways to interpret a signature on a commit:</p> +<ol> +<li> +<p>I assert that this snapshot and commit message were authored as described + in this commit's metadata. (In this interpretation, the signature's + authenticity guarantees do <em>not</em> transitively apply to parents.)</p> +</li> +<li> +<p>I assert that this snapshot and commit message were authored as described + in this commit's metadata, based on exactly the parent commits described. + (In this interpretation, the signature's authenticity guarantees <em>do</em> + transitively apply to parents. This is the interpretation favoured by XXX + LINK HERE XXX.)</p> +</li> +<li> +<p>I assert that this <em>diff</em> and commit message was authored as described in + this commit's metadata. (No assertions about the <em>snapshot</em> are made + whatsoever, and assertions about parentage are barely sensical at all. + This meshes with widespread, diff-oriented policies.)</p> +</li> +</ol> +<h3 id="grafts-and-replacements">Grafts and Replacements</h3> +<p>Git permits post-hoc replacement of arbitrary objects via both the grafts +system (via an untracked, non-distributed file in <code>.git</code>, though some +repositories distribute graft lists for end-users to manually apply) and the +replacements system (via <code>refs/replace/<SHA1></code>, which can optionally be +fetched or pushed). The interaction between these two systems and signature +verification needs to be <em>very</em> closely considered; I've not yet done so.</p> +<p>Cases of note:</p> +<ul> +<li>Neither signature nor subject replaced - the "normal" case</li> +<li>Signature not replaced, subject replaced (by graft, by replacement, by both)</li> +<li>Signature replaced, subject not replaced</li> +<li>Both signature and subject replaced</li> +</ul> +<p>It's tempting to outright disable <code>git replace</code> during signing and +verification, but this will have surprising effects when signing a ref-ish +instead of a bare hash. Since this is the <em>normal</em> case, I think this merits +more thought. (I'm also not aware of a way to disable grafts without +modifying <code>.git</code>, and having the two replacement mechanisms treated +differently may be dangerous.)</p> +<h3 id="no-signed-refs">No Signed Refs</h3> +<p>I mentioned early in this draft that Git's existing signing system doesn't +support signing refs themselves; since refs are an important piece of Git's +workflow ecosystem, this may be a major omission. Unfortunately, this +proposal doesn't address that.</p> +<h2 id="possible-refinements">Possible Refinements</h2> +<ul> +<li>Monotone's certificate system is key+value based, rather than label-based. + This might be useful; while small pools of related values can be asserted + using mutually exclusive policy labels (whose mutual exclusion is a matter + of local interpretation), larger pools of related values rapidly become + impractical under the proposed system.</li> +</ul> +<p>For example, this proposal would be inappropriate for directly asserting + third-party authorship; the asserted author would have to appear in the + policy name itself, exposing the user to a potentially very large number of + similar policy labels.</p> +<ul> +<li> +<p>Ref signing via a manifest (a tree constellation whose paths are ref names + and whose blobs sign the refs' values). Consider cribbing DNSSEC here for + things like lightweight absence assertions, too.</p> +</li> +<li> +<p>Describe how this should interact with commit-duplicating and + commit-rewriting workflows.</p> +</li> +</ul> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/detached-sigs.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/detached-sigs.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/index.html b/.html/git/index.html new file mode 100644 index 0000000..59ee1d4 --- /dev/null +++ b/.html/git/index.html @@ -0,0 +1,109 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + ls /git + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + <span class="list-crumb">list</span> + + </li> + + </ol> + + + + <div id="listing"> + <h1><code>ls /git</code></h1> + + + <div id="directories"> + <h2>Directories</h2> + <ul> + + <li><a href="theory-and-practice/">theory-and-practice/</a></li> + + </ul> + </div> + + + + <div id="pages"> + <h2>Pages</h2> + <ul> + + <li><a href="scratch">Git Is Not Magic</a></li> + + <li><a href="survival">Git Survival Guide</a></li> + + <li><a href="integrate">Integrating with Git: A Field Guide</a></li> + + <li><a href="pull-request-workflow">Life With Pull Requests</a></li> + + <li><a href="detached-sigs">Notes Towards Detached Signatures in Git</a></li> + + <li><a href="stop-using-git-pull-to-deploy">Stop Using Git Pull To Deploy</a></li> + + <li><a href="config">git-config Settings You Want</a></li> + + </ul> + </div> + + + + </div> + + + + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git">See this directory on Bitbucket</a>. + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/integrate.html b/.html/git/integrate.html new file mode 100644 index 0000000..828019f --- /dev/null +++ b/.html/git/integrate.html @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Integrating with Git: A Field Guide + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + integrate + + </li> + + </ol> + + + + <div id="article"> + <h1 id="integrating-with-git-a-field-guide">Integrating with Git: A Field Guide</h1> +<p>Pretty much everything you might want to do to a Git repository when writing +tooling or integrations should be done by shelling out to one <code>git</code> command or +another.</p> +<h2 id="finding-gits-trees">Finding Git's trees</h2> +<p>Git commands can be invoked from locations other than the root of the work +tree or git directory. You can find either of those by invoking <code>git +rev-parse</code>.</p> +<p>To find the absolute path to the root of the work tree:</p> +<pre><code>git rev-parse --show-toplevel +</code></pre> +<p>This will output the absolute path to the root of the work tree on standard +output, followed by a newline. Since the work tree's absolute path can contain +whitespace (including newlines), you should assume every byte of output save +the final newline is part of the path, and if you're using this in a shell +script, quote defensively.</p> +<p>To find the relative path from the current working directory:</p> +<pre><code>git rev-parse --show-cdup +</code></pre> +<p>This will output the relative path to the root of the work tree on standard +output, followed by a newline.</p> +<p>For bare repositories, both commands will output nothing and exit with a zero +status. (Surprise!)</p> +<p>To find <em>a</em> path to the root of the git directory:</p> +<pre><code>git rev-parse --git-dir +</code></pre> +<p>This will output either the relative or the absolute path to the git +directory, followed by a newline.</p> +<p>All three of these commands will exit with non-zero status when run outside of +a work tree or git directory. Check for it.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/integrate.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/integrate.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/pull-request-workflow.html b/.html/git/pull-request-workflow.html new file mode 100644 index 0000000..1a15642 --- /dev/null +++ b/.html/git/pull-request-workflow.html @@ -0,0 +1,163 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Life With Pull Requests + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + pull-request-workflow + + </li> + + </ol> + + + + <div id="article"> + <h1 id="life-with-pull-requests">Life With Pull Requests</h1> +<p>I've been party to a number of discussions with folks contributing to +pull-request-based projects on Github (and other hosts, but mostly Github). +Because of Git's innate flexibility, there are lots of ways to work with pull +requests. Here's mine.</p> +<p>I use a couple of naming conventions here that are not stock <code>git</code>:</p> +<dl> +<dt>origin</dt> +<dd>The repository to which you <em>publish</em> proposed changes</dd> +<dt>upstream</dt> +<dd>The repository from which you receive ongoing development, and which will +receive your changes.</dd> +</dl> +<h2 id="one-time-setup">One-time setup</h2> +<p>Do these things once, when starting out on a project. Keep the results around +for later.</p> +<p>I'll be referring to the original project repository as <code>upstream</code> and +pretending its push URL is <code>UPSTREAM-URL</code> below. In real life, the URL will +often be something like <code>git@github.com:someguy/project.git</code>.</p> +<h3 id="fork-the-project">Fork the project</h3> +<p>Use the repo manager's forking tool to create a copy of the project in your +own namespace. This generally creates your copy with a bunch of useless tat; +feel free to ignore all of this, as the only purpose of this copy is to +provide somewhere for <em>you</em> to publish <em>your</em> changes.</p> +<p>We'll be calling this repository <code>origin</code> later. Assume it has a URL, which +I'll abbreviate <code>ORIGIN-URL</code>, for <code>git push</code> to use.</p> +<p>(You can leave this step for later, but if you know you're going to do it, why +not get it out of the way?)</p> +<h3 id="clone-the-project-and-configure-it">Clone the project and configure it</h3> +<p>You'll need a clone locally to do work in. Create one from <code>origin</code>:</p> +<pre><code>git clone ORIGIN-URL some-local-name +</code></pre> +<p>While you're here, <code>cd</code> into it and add the original project as a remote:</p> +<pre><code>cd some-local-name +git remote add upstream UPSTREAM-URL +</code></pre> +<h2 id="feature-process">Feature process</h2> +<p>Do these things for each feature you work on. To switch features, just use +<code>git checkout my-feature</code>.</p> +<h3 id="create-a-new-feature-branch-locally">Create a new feature branch locally</h3> +<p>We use <code>upstream</code>'s <code>master</code> branch here, so that your feature includes all of +<code>upstream</code>'s state initially. We also need to make sure our local cache of +<code>upstream</code>'s state is correct:</p> +<pre><code>git fetch upstream +git checkout upstream/master -b my-feature +</code></pre> +<h3 id="do-work">Do work</h3> +<p>If you need my help here, stop now.</p> +<h3 id="integrate-upstream-changes">Integrate upstream changes</h3> +<p>If you find yourself needing something that's been added upstream, use +<em>rebase</em> to integrate it to avoid littering your feature branch with +“meaningless” merge commits.</p> +<pre><code>git checkout my-feature +git fetch upstream +git rebase upstream/master +</code></pre> +<h3 id="publish-your-branch">Publish your branch</h3> +<p>When you're “done,” publish your branch to your personal repository:</p> +<pre><code>git push origin my-feature +</code></pre> +<p>Then visit your copy in your repo manager's web UI and create a pull request +for <code>my-feature</code>.</p> +<h3 id="integrating-feedback">Integrating feedback</h3> +<p>Very likely, your proposed changes will need work. If you use history-editing +to integrate feedback, you will need to use <code>--force</code> when updating the +branch:</p> +<pre><code>git push --force origin my-feature +</code></pre> +<p>This is safe provided two things are true:</p> +<ol> +<li><strong>The branch has not yet been merged to the upstream repo.</strong></li> +<li>You are only force-pushing to your fork, not to the upstream repo.</li> +</ol> +<p>Generally, no other users will have work based on your pull request, so +force-pushing history won't cause problems.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/pull-request-workflow.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/pull-request-workflow.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/scratch.html b/.html/git/scratch.html new file mode 100644 index 0000000..ff1bdff --- /dev/null +++ b/.html/git/scratch.html @@ -0,0 +1,134 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Git Is Not Magic + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + scratch + + </li> + + </ol> + + + + <div id="article"> + <h1 id="git-is-not-magic">Git Is Not Magic</h1> +<p>I'm bored. Let's make a git repository out of whole cloth.</p> +<p>Git repos are stored in .git:</p> +<pre><code>fakegit$ mkdir .git +</code></pre> +<p>They have a “symbolic ref” (which are text files, see <a href="http://jk.gs/git-symbolic-ref.html"><code>man +git-symbolic-ref</code></a>) named <code>HEAD</code>, pointing +to the currently checked-out branch. Let's use <code>master</code>. Branches are refs +under <code>refs/heads</code> (see <a href="http://jk.gs/git-branch.html"><code>man git-branch</code></a>):</p> +<pre><code>fakegit ((unknown))$ echo 'ref: refs/heads/master' > .git/HEAD +</code></pre> +<p>The have an object database and a refs database, both of which are simple +directories (see <a href="http://jk.gs/gitrepository-layout.html"><code>man +gitrepository-layout</code></a> and <a href="http://jk.gs/gitrevisions.html"><code>man +gitrevisions</code></a>). Let's also enable the reflog, +because it's a great safety net if you use history-editing tools in git:</p> +<pre><code>fakegit ((ref: re...))$ mkdir .git/refs .git/objects .git/logs +fakegit (master #)$ +</code></pre> +<p>Now <code>__git_ps1</code>, at least, is convinced that we have a working git repository. +Does it work?</p> +<pre><code>fakegit (master #)$ echo 'Hello, world!' > hello.txt +fakegit (master #)$ git add hello.txt +fakegit (master #)$ git commit -m 'Initial commit' +[master (root-commit) 975307b] Initial commit +1 file changed, 1 insertion(+) +create mode 100644 hello.txt + +fakegit (master)$ git log +commit 975307ba0485bff92e295e3379a952aff013c688 +Author: Owen Jacobson <owen.jacobson@grimoire.ca> +Date: Wed Feb 6 10:07:07 2013 -0500 + + Initial commit +</code></pre> +<p><a href="https://www.youtube.com/watch?v=3VwVpaWUu30">Eeyup</a>.</p> +<hr> +<p>Should you do this? <strong>Of course not.</strong> Anywhere you could run these commands, +you could instead run <code>git init</code> or <code>git clone</code>, which set up a number of +other structures, including <code>.git/config</code> and any unusual permissions options. +The key part here is that a directory's identity as “a git repository” is +entirely a function of its contents, not of having been blessed into being by +<code>git</code> itself.</p> +<p>You can infer a lot from this: for example, you can infer that it's “safe” to +move git repositories around using FS tools, or to back them up with the same +tools, for example. This is not as obvious to everyone as you might hope; people </p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/scratch.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/scratch.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/stop-using-git-pull-to-deploy.html b/.html/git/stop-using-git-pull-to-deploy.html new file mode 100644 index 0000000..a3736a0 --- /dev/null +++ b/.html/git/stop-using-git-pull-to-deploy.html @@ -0,0 +1,178 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Stop Using Git Pull To Deploy + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + stop-using-git-pull-to-deploy + + </li> + + </ol> + + + + <div id="article"> + <h1 id="stop-using-git-pull-for-deployment">Stop using <code>git pull</code> for deployment!</h1> +<h2 id="the-problem">The problem</h2> +<ul> +<li>You have a Git repository containing your project.</li> +<li>You want to “deploy” that code when it changes.</li> +<li>You'd rather not download the entire project from scratch for each + deployment.</li> +</ul> +<h2 id="the-antipattern">The antipattern</h2> +<p>“I know, I'll use <code>git pull</code> in my deployment script!”</p> +<p>Stop doing this. Stop teaching other people to do this. It's wrong, and it +will eventually lead to deploying something you didn't want.</p> +<p>Deployment should be based on predictable, known versions of your code. +Ideally, every deployable version has a tag (and you deploy exactly that tag), +but even less formal processes, where you deploy a branch tip, should still be +deploying exactly the code designated for release. <code>git pull</code>, however, can +introduce new commits.</p> +<p><code>git pull</code> is a two-step process:</p> +<ol> +<li>Fetch the current branch's designated upstream remote, to obtain all of the + remote's new commits.</li> +<li>Merge the current branch's designated upstream branch into the current + branch.</li> +</ol> +<p>The merge commit means the actual deployed tree might <em>not</em> be identical to +the intended deployment tree. Local changes (intentional or otherwise) will be +preserved (and merged) into the deployment, for example; once this happens, +the actual deployed commit will <em>never</em> match the intended commit.</p> +<p><code>git pull</code> will approximate the right thing “by accident”: if the current +local branch (generally <code>master</code>) for people using <code>git pull</code> is always clean, +and always tracks the desired deployment branch, then <code>git pull</code> will update +to the intended commit exactly. This is pretty fragile, though; many git +commands can cause the local branch to diverge from its upstream branch, and +once that happens, <code>git pull</code> will always create new commits. You can patch +around the fragility a bit using the <code>--ff-only</code> option, but that only tells +you when your deployment environment has diverged and doesn't fix it.</p> +<h2 id="the-right-pattern">The right pattern</h2> +<p>Quoting <a href="http://gitolite.com/the-list-and-irc/deploy.html">Sitaram Chamarty</a>:</p> +<blockquote> +<p>Here's what we expect from a deployment tool. Note the rule numbers -- +we'll be referring to some of them simply by number later.</p> +<ol> +<li> +<p>All files in the branch being deployed should be copied to the + deployment directory.</p> +</li> +<li> +<p>Files that were deleted in the git repo since the last deployment + should get deleted from the deployment directory.</p> +</li> +<li> +<p>Any changes to tracked files in the deployment directory after the + last deployment should be ignored when following rules 1 and 2.</p> +<p>However, sometimes you might want to detect such changes and abort if +you found any.</p> +</li> +<li> +<p>Untracked files in the deploy directory should be left alone.</p> +<p>Again, some people might want to detect this and abort the deployment.</p> +</li> +</ol> +</blockquote> +<p>Sitaram's own documentation talks about how to accomplish these when +“deploying” straight out of a bare repository. That's unwise (not to mention +impractical) in most cases; deployment should use a dedicated clone of the +canonical repository.</p> +<p>I also disagree with point 3, preferring to keep deployment-related changes +outside of tracked files. This makes it much easier to argue that the changes +introduced to configure the project for deployment do not introduce new bugs +or other surprise features.</p> +<p>My deployment process, given a dedicated clone at <code>$DEPLOY_TREE</code>, is as +follows:</p> +<pre><code>cd "${DEPLOY_TREE}" +git fetch --all +git checkout --force "${TARGET}" +# Following two lines only required if you use submodules +git submodule sync +git submodule update --init --recursive +# Follow with actual deployment steps (run fabric/capistrano/make/etc) +</code></pre> +<p><code>$TARGET</code> is either a tag name (<code>v1.2.1</code>) or a remote branch name +(<code>origin/master</code>), but could also be a commit hash or anything else Git +recognizes as a revision. This will detach the head of the <code>$DEPLOY_TREE</code> +repository, which is fine as no new changes should be authored in this +repository (so the local branches are irrelevant). The warning Git emits when +<code>HEAD</code> becomes detached is unimportant in this case.</p> +<p>The tracked contents of <code>$DEPLOY_TREE</code> will end up identical to the desired +commit, discarding local changes. The pattern above is very similar to what +most continuous integration servers use when building from Git repositories, +for much the same reason.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/stop-using-git-pull-to-deploy.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/stop-using-git-pull-to-deploy.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/survival.html b/.html/git/survival.html new file mode 100644 index 0000000..c1d43ac --- /dev/null +++ b/.html/git/survival.html @@ -0,0 +1,174 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Git Survival Guide + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="./">git</a> + + </li> + + <li class="crumb-2 last"> + + survival + + </li> + + </ol> + + + + <div id="article"> + <h1 id="git-survival-guide">Git Survival Guide</h1> +<p>I think the <code>git</code> UI is pretty awful, and encourages using Git in ways that +will screw you. Here are a few things I've picked up that have saved my bacon.</p> +<ul> +<li>You will inevitably need to understand Git's “internals” to make use of it + as an SCM tool. Accept this early. If you think your SCM tool should not + expose you to so much plumbing, <a href="http://mercurial.selenic.com">don't</a> + <a href="http://bazaar.canonical.com">use</a> <a href="http://subversion.apache.org">Git</a>.<ul> +<li>Git weenies will claim that this plumbing is what gives Git all of its + extra power. This is true; it gives Git the power to get you out of + situations you wouldn't be in without Git.</li> +</ul> +</li> +<li><code>git log --graph --decorate --oneline --color --all</code></li> +<li>Run <code>git fetch</code> habitually. Stale remote-tracking branches lead to sadness.</li> +<li><code>git push</code> and <code>git pull</code> are <strong>not symmetric</strong>. <code>git push</code>'s + opposite operation is <code>git fetch</code>. (<code>git pull</code> is equivalent to <code>git fetch</code> + followed by <code>git merge</code>, more or less).</li> +<li><a href="config">Git configuration values don't always have the best defaults</a>.</li> +<li>The upstream branch of <code>foo</code> is <code>foo@{u}</code>. The upstream branch of your + checked-out branch is <code>HEAD@{u}</code> or <code>@{u}</code>. This is documented in <code>git help + revisions</code>.</li> +<li>You probably don't want to use a merge operation (such as <code>git pull</code>) to + integrate upstream changes into topic branches. The resulting history can be + very confusing to follow, especially if you integrate upstream changes + frequently.<ul> +<li>You can leave topic branches “real” relatively safely. You can do + a test merge to see if they still work cleanly post-integration without + actually integrating upstream into the branch permanently.</li> +<li>You can use <code>git rebase</code> or <code>git pull --rebase</code> to transplant your + branch to a new, more recent starting point that includes the changes + you want to integrate. This makes the upstream changes a permanent part + of your branch, just like <code>git merge</code> or <code>git pull</code> would, but generates + an easier-to-follow history. Conflict resolution will happen as normal.</li> +</ul> +</li> +<li> +<p>Example test merge, using <code>origin/master</code> as the upstream branch and <code>foo</code> + as the candidate for integration:</p> +<pre><code>git fetch origin +git checkout origin/master -b test-merge-foo +git merge foo +# run tests, examine files +git diff origin/master..HEAD +</code></pre> +<p>To discard the test merge, delete the branch after checking out some other +branch:</p> +<pre><code>git checkout foo +git branch -D test-merge-foo +</code></pre> +<p>You can combine this with <code>git rerere</code> to save time resolving conflicts in +a later “real,” permanent merge.</p> +</li> +<li> +<p>You can use <code>git checkout -p</code> to build new, tidy commits out of a branch + laden with “wip” commits:</p> +<pre><code>git fetch +git checkout $(git merge-base origin/master foo) -b foo-cleaner-history +git checkout -p foo -- paths/to/files +# pick out changes from the presented patch that form a coherent commit +# repeat 'git checkout -p foo --' steps for related files to build up +# the new commit +git commit +# repeat 'git checkout -p foo --' and 'git commit' steps until no diffs remain +</code></pre> +<ul> +<li>Gotcha: <code>git checkout -p</code> will do nothing for files that are being + created. Use <code>git checkout</code>, instead, and edit the file if necessary. + Thanks, Git.</li> +<li>Gotcha: The new, clean branch must diverge from its upstream branch + (<code>origin/master</code>, in the example above) at exactly the same point, or + the diffs presented by <code>git checkout -p foo</code> will include chunks that + revert changes on the upstream branch since the “dirty” branch was + created. The easiest way to find this point is with <code>git merge-base</code>.</li> +</ul> +</li> +</ul> +<h2 id="useful-resources">Useful Resources</h2> +<p>That is, resoures that can help you solve problems or understand things, not +resources that reiterate the man pages for you.</p> +<ul> +<li>Sitaram Chamarty's <a href="http://sitaramc.github.com/gcs/">git concepts + simplified</a></li> +<li>Tv's <a href="http://eagain.net/articles/git-for-computer-scientists">Git for Computer + Scientists</a></li> +</ul> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/survival.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/survival.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/theory-and-practice/_list.html b/.html/git/theory-and-practice/_list.html new file mode 100644 index 0000000..feae190 --- /dev/null +++ b/.html/git/theory-and-practice/_list.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + ls /git/theory-and-practice + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="../">git</a> + + </li> + + <li class="crumb-2 not-last"> + + <a href="./">theory-and-practice</a> + + </li> + + <li class="crumb-3 last"> + + <span class="list-crumb">list</span> + + </li> + + </ol> + + + + <div id="listing"> + <h1><code>ls /git/theory-and-practice</code></h1> + + + + + <div id="pages"> + <h2>Pages</h2> + <ul> + + <li><a href="objects">Objects</a></li> + + <li><a href="refs-and-names">Refs and Names</a></li> + + </ul> + </div> + + + + </div> + + + + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/theory-and-practice">See this directory on Bitbucket</a>. + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/theory-and-practice/index.html b/.html/git/theory-and-practice/index.html new file mode 100644 index 0000000..297cbd9 --- /dev/null +++ b/.html/git/theory-and-practice/index.html @@ -0,0 +1,126 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Git Internals 101 + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="../">git</a> + + </li> + + <li class="crumb-2 last"> + + theory-and-practice + + </li> + + </ol> + + + + <div id="article"> + <h1 id="git-internals-101">Git Internals 101</h1> +<p>Yeah, yeah, another article about “how Git works.” There are tons of these +already. Personally, I'm fond of Sitaram Chamarty's <a href="http://gitolite.com/master-toc.html">fantastic series of +articles</a> explaining Git from both ends, +and of <a href="http://eagain.net/articles/git-for-computer-scientists/">Git for Computer +Scientists</a>. Maybe +you'd rather read those.</p> +<p>This page was inspired by very specific, recurring issues I've run into while +helping people use Git. I think Git's “porcelain” layer -- its user interface +-- is terrible, and does a bad job of insulating non-expert users from Git's +internals. While I'd love to fix that (and I do contribute to discussions on +that front, too), we still have the <code>git(1)</code> UI right now and people still get +into trouble with it right now.</p> +<p>Git follows the New Jersey approach laid out in Richard Gabriel's <a href="http://www.dreamsongs.com/RiseOfWorseIsBetter.html">The Rise of +“Worse is Better”</a>: given +the choice between a simple implementation and a simple interface, Git chooses +the simple implementation almost everywhere. This internal simplicity can give +users the leverage to fix the problems that its horrible user interface leads +them into, so these pages will focus on explaining the simple parts and giving +users the tools to examine them.</p> +<p>Throughout these articles, I've written “Git does X” a lot. Git is +<em>incredibly</em> configurable; read that as “Git does X <em>by default</em>.” I'll try to +call out relevant configuration options as I go, where it doesn't interrupt +the flow of knowledge.</p> +<ul> +<li><a href="objects">Objects</a></li> +<li><a href="refs-and-names">Refs and Names</a></li> +</ul> +<p>By the way, if you think you're just going to follow the +<a href="http://git-scm.com/documentation">many</a> +<a href="http://www.atlassian.com/git/tutorial">excellent</a> +<a href="http://try.github.io/levels/1/challenges/1">git</a> +<a href="https://www.kernel.org/pub/software/scm/git/docs/gittutorial.html">tutorials</a> +out there and that you won't need this knowledge, well, you will. You can +either learn it during a quiet time, when you can think and experiment, or you +can learn it when something's gone wrong, and everyone's shouting at each +other. Git's high-level interface doesn't do much to keep you on the sensible +path, and you will eventually need to fix something.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/theory-and-practice/index.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/theory-and-practice/index.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/theory-and-practice/objects.html b/.html/git/theory-and-practice/objects.html new file mode 100644 index 0000000..ff6c53b --- /dev/null +++ b/.html/git/theory-and-practice/objects.html @@ -0,0 +1,202 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Objects + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="../">git</a> + + </li> + + <li class="crumb-2 not-last"> + + <a href="./">theory-and-practice</a> + + </li> + + <li class="crumb-3 last"> + + objects + + </li> + + </ol> + + + + <div id="article"> + <h1 id="objects">Objects</h1> +<p>Git's basest level is a storage and naming system for things Git calls +“objects.” These objects hold the bulk of the data about files and projects +tracked by Git: file contents, directory trees, commits, and so on. Every +object is identified by a SHA-1 hash, which is derived from its contents.</p> +<p>SHA-1 hashes are obnoxiously long, so Git allows you to substitue any unique +prefix of a SHA-1 hash, so long as it's at least four characters long. If the +hash <code>0b43b9e3e64793f5a222a644ed5ab074d8fa1024</code> is present in your repository, +then Git commands will understand <code>0b43</code>, <code>0b43b9</code>, and other patterns to all +refer to the same object, so long as no other object has the same SHA-1 +prefix.</p> +<h2 id="blobs">Blobs</h2> +<p>The contents of every file that's ever been stored in a Git repository are +stored as <code>blob</code> objects. These objects are very simple: they contain the file +contents, byte for byte.</p> +<h2 id="trees">Trees</h2> +<p>File contents (and trees, and Other Things we'll get to later) are tied +together into a directory structure by <code>tree</code> objects. These objects contain a +list of records, with one child per record. Each record contains a permissions +field corresponding to the POSIX permissions mask of the object, a type, a +SHA-1 for another object, and a name.</p> +<p>A directory containing only files might be represented as the tree</p> +<pre><code>100644 blob 511542ad6c97b28d720c697f7535897195de3318 config.md +100644 blob 801ddd5ae10d6282bbf36ccefdd0b052972aa8e2 integrate.md +100644 blob 61d28155862607c3d5d049e18c5a6903dba1f85e scratch.md +100644 blob d7a79c144c22775239600b332bfa120775bab341 survival.md +</code></pre> +<p>while a directory with subdirectories would also have some <code>tree</code> children:</p> +<pre><code>040000 tree f57ef2457a551b193779e21a50fb380880574f43 12factor +040000 tree 844697ce99e1ef962657ce7132460ad7a38b7584 authnz +100644 blob 54795f9b774547d554f5068985bbc6df7b128832 cool-urls-can-change.md +040000 tree fc3f39eb5d1a655374385870b8be56b202be7dd8 dev +040000 tree 22cbfb2c1d7b07432ea7706c36b0d6295563c69c devops +040000 tree 0b3e63b4f32c0c3acfbcf6ba28d54af4c2f0d594 git +040000 tree 5914fdcbd34e00e23e52ba8e8bdeba0902941d3f java +040000 tree 346f71a637a4f8933dc754fef02515a8809369c4 mysql +100644 blob b70520badbb8de6a74b84788a7fefe64a432c56d packaging-ideas.md +040000 tree 73ed6572345a368d20271ec5a3ffc2464ac8d270 people +</code></pre> +<h2 id="commits">Commits</h2> +<p>Blobs and trees are sufficient to store arbitrary directory trees in Git, and +you could use them that way, but Git is mostly used as a revision-tracking +system. Revisions and their history are represented by <code>commit</code> objects, which contain:</p> +<pre><code>* The SHA-1 hash of the root `tree` object of the commit, +* Zero or more SHA-1 hashes for parent commits, +* The name and email address of the commit's “author,” +* The name and email address of the commit's “committer,” +* Timestamps representing when the commit was authored and committed, and +* A commit message. +</code></pre> +<p>Commit objects' parent references form a directed acyclic graph; the subgraph +reachable from a specific commit is that commit's <em>history</em>.</p> +<p>When working with Git's user interface, commit parents are given in a +predictable order determined by the <code>git checkout</code> and <code>git merge</code> commands.</p> +<h2 id="tags">Tags</h2> +<p>Git's revision-tracking system supports “tags,” which are stable names for +specific configurations. It also, uniquely, supports a concept called an +“annotated tag,” represented by the <code>tag</code> object type. These annotated tag +objects contain</p> +<pre><code>* The type and SHA-1 hash of another object, +* The name and email address of the person who created the tag, +* A timestamp representing the moment the tag was created, and +* A tag message. +</code></pre> +<h2 id="anonymity">Anonymity</h2> +<p>There's a general theme to Git's object types: no object knows its own name. +Every object only has a name in the context of some containing object, or in +the context of <a href="refs-and-names">Git's refs mechanism</a>, which I'll get to +shortly. This means that the same <code>blob</code> object can be reused for multiple +files (or, more probably, the same file in multiple commits), if they happen +to have the same contents.</p> +<p>This also applies to tag objects, even though their role is part of a system +for providing stable, meaningful names for commits.</p> +<h2 id="examining-objects">Examining objects</h2> +<ul> +<li> +<p><code>git cat-file <type> <sha1></code>: decodes the object <code><sha1></code> and prints its + contents to stdout. This prints the object's contents in their raw form, + which is less than useful for <code>tree</code> objects.</p> +</li> +<li> +<p><code>git cat-file -p <sha1></code>: decodes the object <code><sha1></code> and pretty-prints it. + This pretty-printing stays close to the underlying disk format; it's most + useful for decoding <code>tree</code> objects.</p> +</li> +<li> +<p><code>git show <sha1></code>: decodes the object <code><sha1></code> and formats its contents to + stdout. For blobs, this is identical to what <code>git cat-file blob</code> would do, + but for trees, commits, and tags, the output is reformated to be more + readable.</p> +</li> +</ul> +<h2 id="storage">Storage</h2> +<p>Objects are stored in two places in Git: as “loose objects,” and in “pack +files.” Newly-created objects are initially loose objects, for ease of +manipulation; transferring objects to another repository or running certain +administrative commands can cause them to be placed in pack files for faster +transfer and for smaller storage.</p> +<p>Loose objects are stored directly on the filesystem, in the Git repository's +<code>objects</code> directory. Git takes a two-character prefix off of each object's +SHA-1 hash, and uses that to pick a subdirectory of <code>objects</code> to store the +object in. The remainder of the hash forms the filename. Loose objects are +compressed with zlib, to conserve space, but the resulting directory tree can +still be quite large.</p> +<p>Packed objects are stored together in packed files, which live in the +repository's <code>objects/pack</code> directory. These packed files are both compressed +and delta-encoded, allowing groups of similar objects to be stored very +compactly.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/theory-and-practice/objects.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/theory-and-practice/objects.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file diff --git a/.html/git/theory-and-practice/refs-and-names.html b/.html/git/theory-and-practice/refs-and-names.html new file mode 100644 index 0000000..fdc56a4 --- /dev/null +++ b/.html/git/theory-and-practice/refs-and-names.html @@ -0,0 +1,199 @@ +<!DOCTYPE html> +<html> +<head> + <title> + The Codex » + Refs and Names + </title> + + <link + rel='stylesheet' + type='text/css' + href='http://fonts.googleapis.com/css?family=Buenard:400,700&subset=latin,latin-ext'> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/reset.css"> + <link + rel="stylesheet" + type="text/css" + href="../../media/css/grimoire.css"> +</head> +<body> + +<div id="shell"> + + <ol id="breadcrumbs"> + + <li class="crumb-0 not-last"> + + <a href="../../">index</a> + + </li> + + <li class="crumb-1 not-last"> + + <a href="../">git</a> + + </li> + + <li class="crumb-2 not-last"> + + <a href="./">theory-and-practice</a> + + </li> + + <li class="crumb-3 last"> + + refs-and-names + + </li> + + </ol> + + + + <div id="article"> + <h1 id="refs-and-names">Refs and Names</h1> +<p>Git's <a href="objects">object system</a> stores most of the data for projects tracked in +Git, but only provides SHA-1 hashes. This is basically useless if you want to +make practical use of Git, so Git also has a naming mechanism called “refs” +that provide human-meaningful names for objects.</p> +<p>There are two kinds of refs:</p> +<ul> +<li> +<p>“Normal” refs, which are names that resolve directly to SHA-1 hashes. These + are the vast majority of refs in most repositories.</p> +</li> +<li> +<p>“Symbolic” refs, which are names that resolve to other refs. In most + repositories, only a few of these appear. (Circular references are possible + with symbolic refs. Git will refuse to resolve these.)</p> +</li> +</ul> +<p>Anywhere you could use a SHA-1, you can use a ref instead. Git interprets them +identically, after resolving the ref down to the SHA-1.</p> +<h2 id="namespaces">Namespaces</h2> +<p>Every operation in Git that uses a name of some sort, including branching +(branch names), tagging (tag names), fetching (remote-tracking branch names), +and pushing (many kinds of name), expands those names to refs, using a +namespace convention. The following namespaces are common:</p> +<ul> +<li> +<p><code>refs/heads/NAME</code>: branches. The branch name is the ref name with + <code>refs/heads/</code> removed. Names generally point to commits.</p> +</li> +<li> +<p><code>refs/remotes/REMOTE/NAME</code>: “remote-tracking” branches. These are maintained + in tandem by <code>git remote</code> and <code>git fetch</code>, to cache the state of other + repositories. Names generally point to commits.</p> +</li> +<li> +<p><code>refs/tags/NAME</code>: tags. The tag name is the ref name with <code>refs/heads/</code> + removed. Names generally point to commits or tag objects.</p> +</li> +<li> +<p><code>refs/bisect/STATE</code>: <code>git bisect</code> markers for known-good and known-bad + revisions, from which the rest of the bisect state can be derived.</p> +</li> +</ul> +<p>There are also a few special refs directly in the <code>refs/</code> namespace, most +notably:</p> +<ul> +<li><code>refs/stash</code>: The most recent stash entry, as maintained by <code>git stash</code>. + (Other stash entries are maintained by a separate system.) Names generally + point to commits.</li> +</ul> +<p>Tools can invent new refs for their own purposes, or manipulate existing refs; +the convention is that tools that use refs (which is, as I said, most of them) +respect the state of the ref as if they'd created that state themselves, +rather than sanity-checking the ref before using it.</p> +<h2 id="special-refs">Special refs</h2> +<p>There are a handful of special refs used by Git commands for their own +operation. These refs do <em>not</em> begin with <code>refs/</code>:</p> +<ul> +<li> +<p><code>HEAD</code>: the “current” commit for most operations. This is set when checking + out a commit, and many revision-related commands default to <code>HEAD</code> if not + given a revision to operate on. <code>HEAD</code> can either be a symbolic ref + (pointing to a branch ref) or a normal ref (pointing directly to a commit), + and is very frequently a symbolic ref.</p> +</li> +<li> +<p><code>MERGE_HEAD</code>: during a merge, <code>MERGE_HEAD</code> resolves to the commit whose + history is being merged.</p> +</li> +<li> +<p><code>ORIG_HEAD</code>: set by operations that change <code>HEAD</code> in potentially destructive + ways by resolving <code>HEAD</code> before making the change.</p> +</li> +<li> +<p><code>CHERRY_PICK_HEAD</code> is set during <code>git cherry-pick</code> to the commit whose + changes are being copied.</p> +</li> +<li> +<p><code>FETCH_HEAD</code> is set by the forms of <code>git fetch</code> that fetch a single ref, and + points to the commit the fetched ref pointed to.</p> +</li> +</ul> +<h2 id="examining-and-manipulating-refs">Examining and manipulating refs</h2> +<p>The <code>git show-ref</code> command will list the refs in namespaces under <code>refs</code> in +your repository, printing the SHA-1 hashes they resolve to. Pass <code>--head</code> to +also include <code>HEAD</code>.</p> +<p>The following commands can be used to manipulate refs directly:</p> +<ul> +<li> +<p><code>git update-ref <ref> <sha1></code> forcibly sets <code><ref></code> to the passed <code><sha1></code>.</p> +</li> +<li> +<p><code>git update-ref -d <ref></code> deletes a ref.</p> +</li> +<li> +<p><code>git symbolic-ref <ref></code> prints the target of <code><ref></code>, if <code><ref></code> is a + symbolic ref. (It will fail with an error message for normal refs.)</p> +</li> +<li> +<p><code>git symbolic-ref <ref> <target></code> forcibly makes <code><ref></code> a symbolic ref + pointing to <code><target></code>.</p> +</li> +</ul> +<p>Additionally, you can see what ref a given name resolves to using <code>git +rev-parse --symbolic-full-name <name></code> or <code>git show-ref <name></code>.</p> + </div> + + + +<div id="comments"> +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +</div> + + + + <div id="footer"> + <p> + + The Codex — + + Powered by <a href="http://markdoc.org/">Markdoc</a>. + +<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/git/theory-and-practice/refs-and-names.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/git/theory-and-practice/refs-and-names.md">history</a>). + + </p> + </div> + +</div> +</body> +</html>
\ No newline at end of file |
