posts:Git:notes: add a quick intro to `git notes`.
authorW. Trevor King <wking@tremily.us>
Tue, 4 Sep 2012 01:34:12 +0000 (21:34 -0400)
committerW. Trevor King <wking@tremily.us>
Wed, 5 Sep 2012 15:02:17 +0000 (11:02 -0400)
posts/Git/notes.org

index 84958f05ce0d69747c6ec2651a950f36419d653c..c177ec3cc9ab6e88bcbe49d192798feb591905e2 100644 (file)
@@ -117,6 +117,12 @@ other fixes on the main branch.
 
 Edit =.git/description=.
 
+** Git notes
+
+http://www.kernel.org/pub/software/scm/git/docs/git-notes.html
+http://git-scm.com/2010/08/25/notes.html
+http://alblue.bandlem.com/2011/11/git-tip-of-week-git-notes.html
+
 * Peripherals
 
 ** GitTorrent
@@ -928,6 +934,448 @@ Since version 1.7.9, Git can sign commits with =-S=.
 
 One more reason to be running =gpg-agent=.
 
+** Fun with =git notes=
+
+*** Creating and showing notes
+
+Say you have a repository
+
+    : $ git log
+    : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:28 2012 -0400
+    : 
+    :     b
+    : 
+    : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:18 2012 -0400
+    : 
+    :     a
+
+You can attach a single note file (per note namespace) to each commit.
+
+    : $ git notes add -m 'note on commit a' HEAD^
+    : $ git notes add -m 'note on commit b' HEAD
+    : $ git notes
+    : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : 068f07ddec5dfe0a8f93721acbdd7da87dd94db2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+
+The output format is =<note blob sha> <commit sha>=.  You can dump a
+note by hand,
+
+    : $ git show 068f07
+    : note on commit a
+
+or show the note associated with an object,
+
+    : $ git notes show HEAD
+    : note on commit b
+
+or show the notes in a log.
+
+    : $ git log --notes
+    : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:28 2012 -0400
+    : 
+    :     b
+    : 
+    : Notes:
+    :     note on commit b
+    : 
+    : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:18 2012 -0400
+    : 
+    :     a
+    : 
+    : Notes:
+    :     note on commit a
+
+*** Altering notes
+
+You can append new content to an existing note,
+
+    : $ git notes append -m 'more notes on commit a' HEAD^
+    : $ git notes show HEAD^
+    : note on commit a
+    : 
+    : more notes on commit a
+
+or spawn your =EDITOR= to make changes.
+
+    : $ EDITOR='sed -i "s/more/many/"' git notes edit HEAD^
+    : $ git notes show HEAD^
+    : note on commit a
+    : 
+    : many notes on commit a
+
+*** Removing notes
+
+You can remove notes.
+
+    : $ git notes remove HEAD^
+    : Removing note for object HEAD^
+    : $ git notes
+    : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
+
+*** Note namespaces
+
+Git notes have their own references in =refs/notes/...=.
+
+    : $ git notes get-ref
+    : refs/notes/commits
+
+You can use other namespaces besides =commits=.
+
+    : $ git notes --ref wtk get-ref
+    : refs/notes/wtk
+    : $ git notes --ref wtk add -m 'wtk note' HEAD
+    : $ git log --notes=wtk
+    : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:28 2012 -0400
+    : 
+    :     b
+    : 
+    : Notes (wtk):
+    :     wtk note
+    : 
+    : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:18 2012 -0400
+    : 
+    :     a
+
+*** Showing notes in the log
+
+If you want to show multiple namespaces in a single log, just keep
+adding =--notes= arguments.
+
+    : $ git log --notes=wtk --notes
+    : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:28 2012 -0400
+    : 
+    :     b
+    : 
+    : Notes:
+    :     note on commit b
+    : 
+    : Notes (wtk):
+    :     wtk note
+    : 
+    : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:21:18 2012 -0400
+    : 
+    :     a
+
+*** Searching notes
+
+You can search through notes for regular expressions.
+
+    : $ git grep wtk refs/notes/wtk
+    : refs/notes/wtk:56db93aebad496c8ec28df0c4c90bed99da57e94:wtk note
+
+The output format here is =<ref>:<commit sha>:<matching line>=.
+
+*** The note branch
+
+Because the notes are stored in their own branch, they have their own
+commit history.
+
+     : $ git log -p notes/commits
+    : commit 0625b737c1dd340122478d8e6ae1fe5f8d8ce183
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:25:24 2012 -0400
+    : 
+    :     Notes removed by 'git notes remove'
+    : 
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : deleted file mode 100644
+    : index 866bab5..0000000
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ /dev/null
+    : @@ -1,3 +0,0 @@
+    : -note on commit a
+    : -
+    : -many notes on commit a
+    : 
+    : commit b046ea813f3e5324e0910da5e60b3aa933aee2ff
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:24:55 2012 -0400
+    : 
+    :     Notes added by 'git notes edit'
+    : 
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : index 975b66d..866bab5 100644
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -1,3 +1,3 @@
+    :  note on commit a
+    :  
+    : -more notes on commit a
+    : +many notes on commit a
+    : 
+    : commit d6f6b1e5c8832552e807bcab723e6eaf07d5e5de
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:24:16 2012 -0400
+    : 
+    :     Notes added by 'git notes append'
+    : 
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : index 068f07d..975b66d 100644
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -1 +1,3 @@
+    :  note on commit a
+    : +
+    : +more notes on commit a
+    : 
+    : commit 76e670903fcf038b602190a2e0314b265d5a34cf
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:22:28 2012 -0400
+    : 
+    :     Notes added by 'git notes add'
+    : 
+    : diff --git a/56db93aebad496c8ec28df0c4c90bed99da57e94 b/56db93aebad496c8ec28df0c4c90bed99da57e94
+    : new file mode 100644
+    : index 0000000..bb511b3
+    : --- /dev/null
+    : +++ b/56db93aebad496c8ec28df0c4c90bed99da57e94
+    : @@ -0,0 +1 @@
+    : +note on commit b
+    : 
+    : commit 62b129c10cdfc8ec9f9d204dac04a5cf0562dffe
+    : Author: W. Trevor King <wking@tremily.us>
+    : Date:   Tue Sep 4 13:22:21 2012 -0400
+    : 
+    :     Notes added by 'git notes add'
+    : 
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : new file mode 100644
+    : index 0000000..068f07d
+    : --- /dev/null
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -0,0 +1 @@
+    : +note on commit a
+
+You can checkout the note branch just like any other branch.
+
+    : $ git checkout notes/commits
+
+Where you will find one file for each note, where the filename is the
+hash of the object that the note is about.
+
+    : $ ls
+    : 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : $ cat 56db93aebad496c8ec28df0c4c90bed99da57e94 
+    : note on commit b
+
+You can do all your usual manipulations in the note branch, merging,
+rebasing, updating refs, etc.
+
+    : $ git update-ref refs/notes/commits b046ea
+    : $ git notes
+    : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : 866bab52944f009b3f92c61beea7a8a7fad0e0a2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+
+*** Adding notes to non-commit objects
+
+There's no reason you need to limit your notes to commits.  However,
+you'll need the hash for the object you're tagging.  Here's how you
+can get a hash for a file:
+
+    : $ git hash-object a
+    : 78981922613b2afb6025042ff6bd878ac1994e85
+
+Alternatively, you can list all the files in a directory.
+
+    : $ ls-tree HEAD^{tree}
+    : 100644 blob 78981922613b2afb6025042ff6bd878ac1994e85    a
+    : 100644 blob 61780798228d17af2d34fce4cfbdf35556832472    b
+
+Then attach your note to the object directly.
+
+    : $ git notes add -m 'note on blob a' 789819
+    : $ $ git notes show $(git hash-object a)
+    : note on blob a
+
+*** Merging notes
+
+**** Naming remote note references
+
+It's a good idea to place all of your note references under
+=refs/notes=, because the current (2012-09-04) implementation of
+=expand_notes_ref= in =git/notes.c= is:
+
+    : void expand_notes_ref(struct strbuf *sb)
+    : {
+    :   if (!prefixcmp(sb->buf, "refs/notes/"))
+    :     return; /* we're happy */
+    :   else if (!prefixcmp(sb->buf, "notes/"))
+    :     strbuf_insert(sb, 0, "refs/", 5);
+    :   else
+    :     strbuf_insert(sb, 0, "refs/notes/", 11);
+    : }
+
+This means that:
+
+    : refs/notes/commits → refs/notes/commits
+    : notes/commits      → refs/notes/commits
+    : commits            → refs/notes/commits
+
+But:
+
+    : refs/remotes/origin/notes/commits → refs/notes/refs/remotes/origin/notes/commits
+
+which is probably not what you wanted.
+
+**** Fast forward merges
+
+You can check out the note branch and pull/push/merge just like any
+other branch, but there is also a user interface for merging notes
+without bothering to checkout the note branch.  To see this in action,
+we'll need to clone our repo.
+
+    : $ cd ..
+    : $ git clone repo-a repo-b
+    : Cloning into 'repo-b'...
+    : done.
+    : $ cd repo-b
+
+Git doesn't fetch (or push) notes by default, so we'll have to add a
+refspec.
+
+    : $ git config --add remote.origin.fetch '+refs/notes/*:refs/notes/remotes/origin/*'
+    : $ git fetch
+    : From ../repo-a
+    :  * [new ref]         refs/notes/commits -> refs/notes/remotes/origin/commits
+    :  * [new ref]         refs/notes/wtk -> refs/notes/remotes/origin/wtk
+
+Alrighty, let's make those note's our own.
+
+    : $ git notes merge origin/notes/commits
+    : fatal: Cannot merge empty notes ref (refs/notes/origin/notes/commits) into empty notes ref (refs/notes/commits)
+
+Hmm, looks like the initial commit may be troublesome.  Let's adopt
+the current remote state.
+
+    : $ git update-ref refs/notes/commits refs/notes/remotes/origin/commits
+    : $ git notes
+    : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
+    : a4c2f4dcfdb7d547bc303282f2678581a9ebf35f 78981922613b2afb6025042ff6bd878ac1994e85
+    : 866bab52944f009b3f92c61beea7a8a7fad0e0a2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+
+And make some changes.
+
+    : EDITOR='sed -i "N;/\nmany/s/\nmany/extra/;P;D"' git notes edit HEAD^
+    : git notes show HEAD^
+    : note on commit a
+    : extra notes on commit a
+
+Now go back to the original repo and fetch the changes.
+
+    : $ cd ../repo-a
+    : $ git remote add repo-b ../repo-b
+    : $ git config --add remote.repo-b.fetch '+refs/notes/*:refs/notes/remotes/repo-b/*'
+    : $ git fetch repo-b
+    : remote: Counting objects: 5, done.
+    : remote: Compressing objects: 100% (2/2), done.
+    : remote: Total 3 (delta 1), reused 0 (delta 0)
+    : Unpacking objects: 100% (3/3), done.
+    : From ../repo-b
+    :  * [new branch]      master     -> repo-b/master
+    :  * [new ref]         refs/notes/commits -> refs/notes/remotes/repo-b/commits
+    : $ git diff notes/commits notes/remotes/repo-b/commits
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : index 866bab5..710e3e0 100644
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -1,3 +1,2 @@
+    :  note on commit a
+    : -
+    : -many notes on commit a
+    : +extra notes on commit a
+
+Merge.
+
+    : $ git notes merge -v remotes/repo-b/commits
+    : Fast-forward
+
+**** Resolving conflicts
+
+Set up conflicting changes.
+
+    : repo-a$ EDITOR='sed -i "s/extra/tons of/"' git notes edit HEAD^
+    : repo-b$ EDITOR='sed -i "s/extra/lots of/"' git notes edit HEAD^
+    : repo-b$ git fetch
+    : remote: Counting objects: 5, done.
+    : remote: Compressing objects: 100% (2/2), done.
+    : remote: Total 3 (delta 1), reused 0 (delta 0)
+    : Unpacking objects: 100% (3/3), done.
+    : From ../repo-a
+    :    69e6240..bf61bfc  refs/notes/commits -> refs/notes/remotes/origin/commits
+    : repo-b$ git diff refs/notes/commits refs/notes/remotes/origin/commits
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : index 0808976..b847e1d 100644
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -1,2 +1,2 @@
+    :  note on commit a
+    : -lots of notes on commit a
+    : +tons of notes on commit a
+
+Try to merge =repo-a= from =repo-b=.
+
+    : $ git notes merge refs/notes/remotes/origin/commits
+    : Auto-merging notes for 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : CONFLICT (content): Merge conflict in notes for object 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : Automatic notes merge failed. Fix conflicts in .git/NOTES_MERGE_WORKTREE and commit the result with 'git notes merge --commit', or abort the merge with 'git notes merge --abort'.
+    : $ ls .git/NOTES_MERGE_WORKTREE/
+    : 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : $ cat .git/NOTES_MERGE_WORKTREE/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : note on commit a
+    : <<<<<<< refs/notes/commits
+    : lots of notes on commit a
+    : =======
+    : tons of notes on commit a
+    : >>>>>>> refs/notes/remotes/origin/commits
+    : $ emacs .git/NOTES_MERGE_WORKTREE/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : <edit as you see fit>
+    : $ git notes merge --commit
+    : $ git notes show HEAD^
+    : note on commit a
+    : zounds of notes on commit a
+
+You can also set some useful merge strategies.  Lets go back and try
+the merge again.  First, undo the merge
+
+    : $ git update-ref refs/notes/commits refs/notes/commits^
+    : $ git diff refs/notes/commits refs/notes/remotes/origin/commits
+    : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : index 0808976..b847e1d 100644
+    : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : @@ -1,2 +1,2 @@
+    :  note on commit a
+    : -lots of notes on commit a
+    : +tons of notes on commit a
+
+Now merge with a particular strategy.
+
+    : $ git notes merge --strategy=cat_sort_uniq refs/notes/remotes/origin/commits
+    : Concatenating unique lines in local and remote notes for 84b126ce36567260bef8d0bbea03d426c9b7aa6d
+    : $ git notes show HEAD^
+    : lots of notes on commit a
+    : note on commit a
+    : tons of notes on commit a
+
+There are more details about the available merge strategies in =git
+notes --help=.
+
 * Troubleshooting
 ** Git commit hangs with no output