From: W. Trevor King Date: Tue, 4 Sep 2012 01:34:12 +0000 (-0400) Subject: posts:Git:notes: add a quick intro to `git notes`. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=31e40c3d5664dfee4f6ee68d20c978e936cdfc8d;p=blog.git posts:Git:notes: add a quick intro to `git notes`. --- diff --git a/posts/Git/notes.org b/posts/Git/notes.org index 84958f0..c177ec3 100644 --- a/posts/Git/notes.org +++ b/posts/Git/notes.org @@ -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 + : Date: Tue Sep 4 13:21:28 2012 -0400 + : + : b + : + : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d + : Author: W. Trevor King + : 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 = =. 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 + : Date: Tue Sep 4 13:21:28 2012 -0400 + : + : b + : + : Notes: + : note on commit b + : + : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d + : Author: W. Trevor King + : 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 + : Date: Tue Sep 4 13:21:28 2012 -0400 + : + : b + : + : Notes (wtk): + : wtk note + : + : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d + : Author: W. Trevor King + : 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 + : 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 + : 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 =::=. + +*** 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 + : 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 + : 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 + : 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 + : 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 + : 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 + : + : $ 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