64632ad1b50ce2700e0f0bd90620ca7ffaebb267
[mw2txt.git] / posts / Git / notes.org
1 * Overview
2
3 Git is a distributed vesioning control system.
4
5 * References
6
7 ** Overviews
8
9 *** DONE [[http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/][Git vs. Mercurial blog entry: MacGyver vs. Bond]]
10     CLOSED: [2008-08-28 Thu 05:06]
11     - State "DONE"       [2008-08-28 Thu 05:06]
12     - State "TODO"       [2008-08-28 Thu 05:06]
13
14 A nice, touchy-feely intro to the difference between Git and
15 Mercurial.  Despite the one-stop-shopping-appeal of Mercurial, I will
16 go with my command-line-linux-philosophy-loving, blogs-with-ikiwiki
17 heart and head into git-land.
18
19 ** Tutorials
20
21 *** TODO [[http://rubinius.lighthouseapp.com/projects/5089/using-git][Rubinius git page]] Get going fast
22     - State "TODO"       [2008-08-28 Thu 05:06]
23
24 *** TODO [[http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html][gittutorial]] The official intro ;), looks fairly readable…
25     - State "TODO"       [2008-08-28 Thu 05:11]
26
27 *** TODO [[http://www.kernel.org/pub/software/scm/git/docs/everyday.html][Everyday GIT With 20 Commands Or So]] Nicely broken down by goal
28     - State "TODO"       [2008-08-28 Thu 05:06]
29
30 *** TODO [[http://book.git-scm.com/][Git Community Book]] Open source wiki/howto website
31   :PROPERTIES:
32   :CUSTOM_ID: git-book
33   :END:
34     - State "TODO"       [2008-08-28 Thu 05:06]
35
36 ** Interface with SVN
37
38 *** TODO [[http://newartisans.com/blog_files/diving.into.git.php][Diving into git blog entry]] Importing the Subversion history
39     - State "TODO"       [2008-08-28 Thu 05:06]
40
41 *** TODO [[http://git.or.cz/course/svn.html][Git - SVN Crash Course]] ?
42     - State "TODO"       [2008-08-28 Thu 05:06]
43
44 *** TODO [[http://utsl.gen.nz/talks/git-svn/intro.html][An introduction to git-svn for Subversion/SVK users and deserters]]
45     - State "TODO"       [2008-08-28 Thu 06:09]
46
47 Lots of political digression, but also lots of useful info.  Your call.
48
49 ** Enforcing development policies
50
51 *** TODO [[http://www.kernel.org/pub/software/scm/git/docs/howto/update-hook-example.txt][Push hooks]]
52     - State "TODO"       [2008-08-28 Thu 05:16]
53
54 Push hooks
55
56 *** DONE [[http://blog.offbytwo.com/2008/04/16/running-nosetests-as-a-git-pre-commit-hook/][Pre commit hooks]]
57     CLOSED: [2008-09-02 Tue 08:48]
58     - State "DONE"       [2008-09-02 Tue 08:48]
59     - State "TODO"       [2008-09-02 Tue 08:46]
60
61 Basically, put whatever you want in =.git/hooks/pre-commit=.
62 For example, I added:
63
64     : ./.git/hooks/pre-commit-make-check || exit 1
65
66 right after the initial comments with
67
68     : $ cat .git/hooks/pre-commit-make-check
69     : make check
70
71 Don't forget to =chmod 744= both scripts to make them executible.
72 Also note that these scripts are run from the base repo directory,
73 which is why I had to include the relative path to
74 =pre-commit-make-check=, and didn't need =cd ../../= in the check
75 script.
76
77 *** DONE [[http://changelog.complete.org/posts/586-Rebase-Considered-Harmful.html][Rebase Considered Harmful]]
78     CLOSED: [2008-08-28 Thu 05:27]
79     - State "DONE"       [2008-08-28 Thu 05:27]
80     - State "TODO"       [2008-08-28 Thu 05:18]
81
82 A “keep the warts” vs. “stay true to history” monologue.  Advocates
83 against rebasing public repos because (quotes from the git-rebase
84 manpage):
85
86       "When you rebase a branch, you are changing its history in a way
87       that will cause problems for anyone who already has a copy of
88       the branch in their repository and tries to pull updates from
89       you."
90
91 Personally, I feel like a middle ground, where private mini-branches
92 get a little constructive history tweaking is a good thing.  Noone
93 cares about typos in comments, and it adds noise to the development
94 signal, so fix those commits in your private branch.  Once you go
95 public though, don't mess with the history, since it would be even
96 more confusing to have conflicting histories in seperate public
97 repositories.  Anything serious enough to require a altering the
98 author field should probably not be changed.
99
100 My thoughts are shared by others, for example commenter #7 Jing Xue.
101 However, commenter #8 links to [[http://www.reddit.com/r/programming/comments/6ube0/synchronizing_development_rebase_vs_pullmerge_git/?sort=top][Synchronizing development: rebase
102 vs. pull+merge, GIT vs. Mercurial]], where oddbod points out that the
103 real problem when “mid-level”, public repos rebase to avoid sending
104 known-bugged patches upstream.  He says they avoid the obviously
105 better solution of sending up the bad patch with a patch-patch hard on
106 its heels, which would avoid rebasing a public repo, and still
107 preserve the spirit and authorship of the changes.
108
109 **** Aside: rebase etymology
110
111 I just realized that “rebasing” is attaching your branch to a
112 different base point on the tree.  Afterward, it looks like you made
113 all of your adjustments right now, not in parallel with a bunch of
114 other fixes on the main branch.
115
116 ** Setting a description for your repo
117
118 Edit =.git/description=.
119
120 ** Git notes
121
122 http://www.kernel.org/pub/software/scm/git/docs/git-notes.html
123 http://git-scm.com/2010/08/25/notes.html
124 http://alblue.bandlem.com/2011/11/git-tip-of-week-git-notes.html
125
126 * Peripherals
127
128 ** GitTorrent
129
130 People are indeed working on [[http://gittorrent.utsl.gen.nz/rfc.html][the obvious protocol]].
131
132 ** The git-* to git * transition
133
134 The transition occured between git 1.5.4 and 1.6.0.  See the [[http://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.6.0.txt][1.6.0
135 release notes]] for details.
136
137 * Case studies
138
139 ** Gitting =chem_web=, my first git project
140
141 *** Repository creation and setup
142 From the [[#git-book][Git Community Book]].
143
144 *** Install
145
146     : $ apt-get install git-core gitk
147
148 *** Setup
149 From the [[http://book.git-scm.com/2_setup_and_initialization.html][Git Community Book]].
150
151 By default that file is =~/.gitconfig= and the contents will then look like this:
152
153     : [user]
154     :         name = W. Trevor King
155     :         email = wking at drexel dot edu
156
157 *** Initialize repository
158 From the [[http://book.git-scm.com/3_getting_a_git_repository.html][Git Community Book]].
159
160     : $ cd ~/rsrch/chem_web
161     : $ git init
162
163 *** Add some files to the repository
164 From the [[http://book.git-scm.com/3_normal_workflow.html][Git Community Book]].
165
166     : $ git add README *.py docs templates
167     : $ git status
168
169 Oops, =git add= adds all of a directory's contents too.  Remove some
170 of the automatically generated files.  =git rm= removes a file from
171 both the working directory and the index.  I wish I could just remove
172 from the index, but I'm not sure how yet.  Ah well, the reason I want
173 to remove them is that they are automatically generated ;).
174
175     : $ git rm -f docs/*.pdf
176     : ...
177
178 a bunch of other work while I clean up the mess I've made.  Keep going
179 until =git status= looks right.
180
181 *** Commit the code to the master branch
182 From the [[http://book.git-scm.com/3_normal_workflow.html][Git Community Book]].
183
184     : $ git commit
185
186 Or you can automatically add any changed tracked-files with
187
188     $ git commit -a
189
190 *** Creating the development branch
191 From the [[http://book.git-scm.com/3_basic_branching_and_merging.html][Git Community Book]].
192
193 My workflow will be in two branches:
194
195  * =master=, the current stable/working release
196  * =dev=, the feature development branch
197
198 I will develop new code in =dev= until I am happy with its
199 performance, and then merge back into the master branch.  Old bugs
200 will be fixed in the master branch, and then cherry-picked into the
201 dev branch.  That's the current plan anyway ;).  Create the =dev=
202 branch with
203
204     : $ git branch dev
205
206 *** Changing branches and coding
207 From the [[http://book.git-scm.com/3_basic_branching_and_merging.html][Git Community Book]].
208
209 List branches with
210
211     : $ git branch
212
213 Change to dev with
214
215     : $ git checkout dev
216
217 Now add that cool new feature, NFPA diamonds for the cabinets :p.
218 When you feel it is appropriate, commit your changes in the local
219 branch with
220
221     : $ git commit -a
222
223 *** Correcting private commit mistakes
224 From the [[http://book.git-scm.com/4_undoing_in_git_-_reset%2C_checkout_and_revert.html][Git Community Book]].
225
226 Oops, I forgot X or made a typo in my commit message.  My =dev= branch
227 is not public, so go ahead and fix the mistake.  Then run
228
229     : $ git commit --amend
230
231 This may leave some danglers
232
233     : $ git fsck
234     : dangling blob 03cabac5fa426ca8df4dff1fdb2596b68d2f4c5a
235     : dangling blob 87488a0b4ea976127d6b9171ef6f10941a1dd74e
236     : ...
237
238 which you can clean up with
239
240     : $ git prune
241
242 *** Bring the master branch up to speed
243 From the [[http://book.git-scm.com/3_basic_branching_and_merging.html][Git Community Book]].
244
245     : $ git checkout master
246     : $ git merge dev
247
248 You may have to deal with a [[#conflicting-merge][conflicting merge]].
249
250 *** Delete a branch
251 From the [[http://book.git-scm.com/3_basic_branching_and_merging.html][Git Community Book]].
252
253     : $ git branch -d dev
254
255 The =-d= ensures the changes have already been merged back into the
256 current branch.  If you want to kill the brach without merging use
257
258     : $ git branch -D dev
259
260 *** Repository maitenance
261 From the [[http://book.git-scm.com/4_maintaining_git.html][Git Community Book]].
262
263 Recompress (to keep the compression most effective)
264
265     : $ git gc
266
267 Check repository consitency
268
269     : $ git fsck
270
271 Both should be run manually from time to time.
272
273 *** Working over a network
274 From the [[http://book.git-scm.com/3_distributed_workflows.html][Git Community Book]].
275
276 **** Grab a remote repository
277
278 A remote friend wants to work on your code, or more likely, you're at
279 home and you want to work on your code at work.  Grab the repo using
280 ssh with
281
282     : $ git clone ssh://wking@loki/~/rsrch/chem_inventory ci
283
284 using the
285
286     : ssh://[user@]host.xz/~/path/to/repo.git
287
288 git URL notation listed in =man git-clone=.
289
290 **** Possibly remove the reference to the remote repository
291
292 If you're decomissioning the remote repository, you can remove it from
293 the current one with
294
295     : $ git remote rm <name>
296
297 **** Work on the repository
298
299 Nothing changes here.
300
301 **** Get your remote partner to pull your changes back upstream
302
303     : $ git remote add bob /home/bob/repo
304     : $ git fetch remote
305     : $ git log -p dev remotes/bob/master
306     : $ git merge remotes/bob/master
307
308 and possibly
309
310     : $ git remote rm bob
311
312 ** Gitting sawsim, migration from svn
313
314 *** Install git
315
316     : $ apt-get install git-core git-svn gitk
317
318 *** Repository migration from svn
319   :PROPERTIES:
320   :CUSTOM_ID: svn-migration
321   :END:
322
323 Following [[http://github.com/maddox][Jon Maddox]] at the [[http://www.simplisticcomplexity.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository/][Simplistic Complexity blog]].
324
325 **** Create the decoy directory
326
327 =git svn= keeps some info about the svn repository, to make it easier
328 to keep the two in sync.  However we are not interested in staying in
329 sync, we just want to move to Git.  Create a decoy Git version of the
330 repo with
331
332     : $ mkdir sawsim.svn
333     : $ cd sawsim.svn
334     : $ git svn init svn://abax.physics.drexel.edu/sawsim/trunk/
335     : $ cat >> .git/config <<EOF
336     : [svn]
337     :   authorsfile = users.txt
338     : EOF
339     : $ cat > users.txt <<EOF
340     : wking = W. Trevor King <wking at drexel dot edu>
341     : EOF
342     : $ git svn fetch
343
344 Jon Maddox suggests using
345
346     : $ git config svn.authorsfile ~/Desktop/users.txt
347
348 instead of my manual =.git/config= editing, but my stock Debian git
349 (1.4.4.4) doesn't seem to have =git config=.  No big deal.
350
351 Check that this worked and translated your users correctly with
352
353     : $ git log
354
355 ***** Warning: here documents
356
357 Some shells might not like my [[http://tldp.org/LDP/abs/html/here-docs.html][here document]] Bash syntax.  In that
358 case, write the files another way.
359
360 **** Create the clean directory
361
362 When we clone the decoy directory, all the svn junk gets left behind.
363
364 First, leave the sawsim.svn directory
365
366     : $ cd ..
367
368 and clone like you normally would
369
370     : $ git clone sawsim.svn sawsim
371
372 You don't need the =[svn]= stuff in =.git/config= anymore either.
373 I don't remember if they came over on their own or not…
374
375 I removed the origin information with
376
377     : $ rm .git/remotes/origin
378
379 Although a better approach would probably be
380
381     : $ git remote rm origin
382
383 *** Setup
384
385 **** gitignore
386 From =man gitignore=
387
388 The sawsim code is mostly in a single [[http://www.cs.tufts.edu/~nr/noweb/][noweb]] file.  Extracting all the
389 source from the file creates lot of indirectly versioned clutter.  To
390 avoid having all your =git status= calls swamped with untracked files,
391 Just add the filenames (globbing allowed) to =.gitignore=.
392
393 **** Push hooks
394      TODO
395
396 *** Making your repository public/Publishing your repository
397 From the [[http://book.git-scm.com/4_setting_up_a_public_repository.html][Git Community Book]]
398
399 To distribute your repo via HTTP (easier on someone else's server).
400
401     : user@devel$ ssh server
402     : server$ cd ~/public_html
403     : server$ git clone --bare ssh://user@devel/~/path/to/repo.git repo.git
404     : server$ cd repo.git
405     : server$ touch git-daemon-export-ok
406     : server$ git --bare update-server-info
407     : server$ chmod a+x hooks/post-update
408
409 Others can clone or pull from your URL with
410
411     : anon$ git clone http://server/~you/repo.git
412
413 From the [[http://book.git-scm.com/3_distributed_workflows.html][Git Community Book]]
414
415 Once you've set up your repo, you can push changes to it with =ssh=
416
417     : devel$ git push ssh://user@server/~/public_html/repo.git master
418
419 To save typing, add
420
421     : [remote "public"]
422     :     url = ssh://user@server/~/public_html/repo.git
423
424 to =.git/config=, after which you can push with
425
426     : devel$ git push public master
427
428 Note that you may need to copy =.git/description= over by hand.  I
429 wrote up a [[http://blog.tremily.us/posts/Git/git-publish.py][git-publish]] script to automate this.
430
431 ** Gitting comedi, using Git as a frontend for CVS
432 From [[http://issaris.blogspot.com/2005/11/cvs-to-git-and-back.html][Takis blog]]
433
434 *** Repository creation and setup
435
436 This is quite similar to [[#svn-migration][svn migration]].
437
438 **** Create the decoy directory
439
440     : $ mkdir comedi.cvs
441     : $ cd comedi.cvs
442     : $ #cvs -d :pserver:anonymous@cvs.comedi.org:/cvs/comedi login
443     : $ git cvsimport -p x -v -d :pserver:anonymous@cvs.comedi.org:/cvs/comedi comedi
444
445 The login line may not be necessary for other CVS projects.
446 Arguments to =git cvsimport=:
447
448  |----------+---------------------------------------------------------------------|
449  | Option   | Meaning                                                             |
450  |----------+---------------------------------------------------------------------|
451  | =-p x=   | Pass =-x= to =cvsps=, which ignores any =~/.cvsps/cvsps.cache= file |
452  |----------+---------------------------------------------------------------------|
453  | =-v=     | Verbose                                                             |
454  |----------+---------------------------------------------------------------------|
455  | =-d ...= | From http://www.comedi.org/download.html                            |
456  |----------+---------------------------------------------------------------------|
457
458
459 **** Create the clean directory
460
461     : $ cd ..
462     : $ git clone comedi.cvs comedi
463
464 *** Do your work like normal in comedi
465 *** Update with the latest cvs
466
467     : $ cd comedi.cvs
468     : $ git cvsimport -p x -v -d :pserver:anonymous@cvs.comedi.org:/cvs/comedi comedi
469     : $ cd ../comedi
470     : $ git pull
471
472 You may have to deal with a [[#conflicting-merge][conflicting merge]].
473
474 *** Create a patch against the cvs source
475
476     : $ git format-patch origin
477
478 * Other useful examples
479 ** Purge all knowledge of a given file or subdir from history
480
481 For example, in case you accidentally started versioning =/etc/shadow=,
482 or some other document containing sensative information.
483
484     : $ git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch /etc/shadow'
485     : $ git reflog expire --expire=0 --all
486     : $ git prune
487     : $ git repack -adf
488
489 ** Rewrite the repository to look as if foodir/ had been its project root
490
491 Discarding all other history
492
493     : $ git filter-branch --subdirectory-filter foodir -- --all
494
495 ** Merge a single file (with history) into another repository
496
497 Merge the file =myfile= (with history) from =REPO_A= into =REPO_B=.
498
499 Create a filtered version of =REPO_A=:
500
501     : $ git clone REPO_A work-a
502     : $ cd work-a
503     : $ SPELL='git ls-tree -r --name-only --full-tree "$GIT_COMMIT" | grep -v "[.]git/\|myfile" | grep -v "^[.]git\$" | tr "\n" "\0" | xargs -0 git rm --cached -r --ignore-unmatch'
504     : $ git filter-branch --prune-empty --index-filter "$SPELL" -- --all
505
506 Alter the =grep= stuff as you need.  The goal is to remove anything
507 you want to keep from the listing produced by =SPELL=.  If the spell
508 becomes too complicated, you can move it to a standalone script:
509
510     : $ cat /tmp/spell.sh
511     : #!/bin/bash
512     : git ls-tree -r …
513     : …
514     : $ git filter-branch --prune-empty --index-filter /tmp/spell.sh -- --all
515
516 Merge it into =REPO_B=:
517
518     : $ cd ..
519     : $ git clone REPO_B work-b
520     : $ git remote add myfile-repo ../work-a
521     : $ git pull myfile-repo master
522     : $ git remote rm myfile-repo
523
524 Clean up:
525
526     : $ cd ..
527     : $ rm -rf work-a REPO_B
528     : $ mv work-b REPO_B
529
530 Thanks to [[http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/][Greg Bayer]] and [[http://stackoverflow.com/questions/7375528/how-to-extract-one-file-with-commit-history-from-a-git-repo-with-index-filter][Peter Hillerström]].
531
532 ** Cherry pick a commit from another repository
533
534 First, give the remote repository a nickname (optional)
535
536     : $ git remote add bob /home/bob/myrepo
537
538 Then fetch the remote repo
539
540     : $ git fetch bob
541
542 You can merge all the changes Bob made to his master branch with
543
544     : $ git pull . remotes/bob/master
545
546 Or cherry-pick a particular one, e.g. commit =1d8fb1fe41dfc1b1eb38c7b5d574577c4b341c58=
547
548     : $ git cherry-pick 1d8fb1fe41dfc1b1eb38c7b5d574577c4b341c58
549
550 When a particular remote repo no longer contains interesting material,
551 you can purge the fetched tags and objects with
552
553     : $ git remote rm bob
554     : $ git remote prune bob
555
556 ** Restore a deleted file to match an earlier version
557 Source: [[http://stackoverflow.com/questions/953481/restore-a-deleted-file-in-a-git-repo][stackoverflow]].
558
559 Find the commit that deleted the file in question
560
561     : $ git rev-list -n 1 HEAD -- <file_path>
562
563 or
564
565     : $ git log --diff-filter=D --summary
566
567 Then checkout the file
568
569     : $ git checkout <deleting_commit>^ -- <file_path>
570
571 ** Move master.HEAD to a different location
572
573 Sometimes you screw up and want to drop the thread you've been working
574 on.  Place the =HEAD= of the master branch on commit =XYZ= with
575
576     : $ git checkout XYZ
577     : $ git branch -D master
578     : $ git branch master XYZ
579     : $ git checkout master
580
581 Note that this may remove some information from your =.git/config='s
582 =[branch "master"]= entry.  You should save your earlier =.git/config=
583 before doing it, and make any appropriate corrections afterwards.
584
585 If you're just trying to roll back a branch a few commits, skip the
586 above and try
587
588     : $ git reset --hard HEAD^
589
590 or add however many =^= you need to get back to the last good commit.
591
592 *** Rewinding bare repositories
593
594 If you're trying to [[http://stackoverflow.com/questions/4624881/how-can-i-uncommit-the-last-commit-in-a-git-bare-repository][roll back a few commits in a bare repository]]
595 you'll need to use:
596
597     : $ git update-ref HEAD HEAD^
598
599 If you're in another branch, use:
600
601     : $ git update-ref refs/heads/branch-name branch-name^
602
603 And if you're going back further, use the sha1:
604
605     : $ git update-ref refs/heads/branch-name a12d48e2
606
607 ** Git submodules, nesting/tracking sub-repositories.
608
609 This is a nice way of grouping associated projects.  The submodules
610 are included as stand-alone repositories, and the super-project has
611 pointers picking out a particular revision of each submoduel.  See the
612 related [[#git-subtrees][Git subtrees]] for an alternate approach.
613
614 *** References
615     [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
616     [[http://book.git-scm.com/5_submodules.html][Git Book]]
617     [[http://speirs.org/2009/05/11/understanding-git-submodules/][Fraser Speirs: Understanding Git Submodules]]
618
619 *** Setup a super-module
620 From the [[http://book.git-scm.com/5_submodules.html][Git Book]]
621
622     : $ git submodule add ~/path/to/submoduleX $submoduleX
623
624 Warning: Do not use local URLs here if you plan to publish your
625 supermodule.  =git submodule add=
626
627  * clones the submodule under the current directory and by default
628    checks out the master branch.
629  * adds the submodule's clone path to the gitmodules file and adds
630    this file to the index, ready to be committed.
631  * adds the submodule's current commit ID to the index, ready to be
632    committed.
633
634     : $ git submodule init
635
636 *** Cloning a super-module
637 From the [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
638
639 Grab the content living in the super module itself
640
641     : $ git clone ~/subtut/public/super
642
643 See how the submodules look
644
645     : $ git submodule status
646     : -d266b9873ad50488163457f025db7cdd9683d88b a
647     : ...
648
649 Add submodule repository URLs to .git/config
650
651     : $ git submodule init
652
653 Check that they're there if you like
654
655     : $ git config -l
656     : ...
657     : submodule.a.url=/home/moses/subtut/public/a/.git
658
659 Now check out the referenced submodules
660
661     : $ git submodule update
662
663 *** Changing submodules from supermodules
664 From the [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
665
666 To update a submodule, remember that it's just a checked-out branch in
667 your supermodule.  Create and publish the change using the usual
668 method:
669
670     : $ cd a
671     : a$ git branch
672     : * (no branch)
673     :   master
674     : a$ git checkout master
675     : a$ echo "adding a line again" >> a.txt
676     : a$ git commit -a -m "Updated the submodule from within the superproject."
677     : a$ git push
678     : $ cd ..
679
680 Now point the supermodule at the new commit.  Warning: don't use
681 =git add a/= or git will think you mean to add the contents of the
682 directory.  For submodule updates, you must leave off the trailing
683 slash.
684
685     : $ git add a
686     : $ git commit -m "Updated submodule a."
687     : $ git show
688     : ...
689     : diff --git a/a b/a
690     : index d266b98..261dfac 160000
691     : --- a/a
692     : +++ b/a
693     : @@ -1 +1 @@
694     : -Subproject commit d266b9873ad50488163457f025db7cdd9683d88b
695     : +Subproject commit 261dfac35cb99d380eb966e102c1197139f7fa24
696
697 Take a look at the submodule changes from the supermodule.
698
699     : $ git submodule summary HEAD^
700     : * a d266b98...261dfac (1):
701     :   > Updated the submodule from within the superproject.
702
703 Publish your updated supermodule.
704
705     : $ git push
706
707 *** Removing submodules
708 From the [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
709
710 1. Delete the relevant line from the =.gitmodules= file.
711 2. Delete the relevant section from =.git/config=.
712 3. Run =git rm --cached path_to_submodule= (no trailing slash).
713 4. Commit and delete the now untracked submodule files.
714
715 *** Warnings
716 From the [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
717
718 It's not safe to run =git submodule update= if you've made changes
719 within a submodule. They will be silently overwritten:
720
721 **** Example
722 From the [[http://git.or.cz/gitwiki/GitSubmoduleTutorial][Git Wiki]]
723
724     : a$ cat a.txt
725     : module a
726     : a$ echo line added from private2 >> a.txt
727     : a$ git commit -a -m "line added inside private2"
728     : $ cd ..
729     : $ git submodule update
730     : Submodule path 'a': checked out 'd266b9873ad50488163457f025db7cdd9683d88b'
731     : $ cat a/a.txt
732     : module a
733
734 The changes are still visible in the submodule's reflog:
735
736     : $ git log -g --pretty=oneline
737     : d266b9873ad50488163457f025db7cdd9683d88b HEAD@{0}: checkout: moving to d266b9873ad50488163457f025db7
738     : 4389b0d8e22e616c88a99ebd072cfebba40797ef HEAD@{1}: commit: line added inside private2
739     : d266b9873ad50488163457f025db7cdd9683d88b HEAD@{2}: checkout: moving to d266b9873ad50488163457f025db7
740
741 ** Git subtrees, merging an entire repository into a subdirectory of your repository
742   :PROPERTIES:
743   :CUSTOM_ID: git-subtrees
744   :END:
745
746 *** Setup
747 From [[http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html][kernel.org: merge-subtree]]
748
749 Name the other project =Bproject=, and fetch.
750
751     : $ git remote add -f Bproject /path/to/B
752
753 Prepare for the later step to record the result as a merge.
754 (=-s ours= selects the merge strategy as "keep our version")
755
756     : $ git merge -s ours --no-commit Bproject/master
757
758 Read =master= branch of =Bproject= to the subdirectory =dir-B=.
759
760     : $ git read-tree --prefix=dir-B/ -u Bproject/master
761
762 Record the merge result.
763
764     : $ git commit -m "Merge B project as our subdirectory"
765
766 *** Keeping up to date with the sub-repository source
767
768 Maintain the result with subsequent pulls/merges using "subtree"
769
770     : $ git pull -s subtree Bproject master
771
772 *** Pulling changes back into the sub-repository source
773 From [[http://github.com/apenwarr/git-subtree/tree/master][git-subtree]]
774
775 The super-project makes some local alterations.  Pull/merge them
776 with =git subtree=.
777
778 ** Backdating Git tags
779
780 I rarely bother tagging my projects in the early stages.  This is
781 probably a mistake ;), but Git makes it easy to add backdated tags
782 later on:
783
784     : $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
785
786 (from =git tag --help=).  Note that you will probably be tagging a
787 previous commit
788
789     : $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1 <commit>
790
791 ** Inline word diff
792 [[http://mislav.uniqpath.com/2010/07/git-tips/][mislav]]
793
794
795     : $ git diff --word-diff
796
797 ** Find out if a change is part of a release
798
799     : $ git name-rev --tags 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
800     : 33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99~940
801
802 Now you are wiser, because you know that it happened 940 revisions
803 before v0.99.  A similar command is =git describe=, which finds the
804 latest tag in a commit's history and uses that to construct a name:
805
806     : $ git describe v1.0.5^2
807     : tags/v1.0.0-21-g975b31d
808
809 ** List unmerged commits
810
811 To see what's outstanding in a given branch
812
813     : $ git cherry [-v] [<upstream> [<head> [<limit>]]]
814
815 The =-v= option prints summaries as well as the usual commit hashes.
816
817 ** Remove a remote branch
818
819 If you want to delete a branch from a repository to which you only
820 have push access, use:
821
822     : git push repository :branch
823
824 after deleting the branch in your local repository.
825
826 ** Clean out your working directory
827
828 To list files that will be removed (a dry run), use:
829
830     : git clean -dxn
831
832 Then remove the files with
833
834     : git clean -dxf
835
836  |--------+-------------------------------------------------------------|
837  | Option | Meaning                                                     |
838  |--------+-------------------------------------------------------------|
839  | =-d=   | Remove untracked directories in addition to untracked files |
840  |--------+-------------------------------------------------------------|
841  | =-x=   | Don’t use the ignore rules (remove all untracked files)     |
842  |--------+-------------------------------------------------------------|
843  | =-n=   | Dry run                                                     |
844  |--------+-------------------------------------------------------------|
845  | =-f=   | Force                                                       |
846  |--------+-------------------------------------------------------------|
847
848 ** Bisecting a kernel bug (i.e. manual bisection)
849
850 Although it is possible to automate this (if you have two boxes, one
851 to build kernels and drive the bisection, and one to boot them and
852 check the results), it is also possible to bisect kernel bugs "by
853 hand" using =git bisect=.  The man page does a better job describing
854 the process than I will.
855
856 Note that Git will track the bisection state across reboots, which is
857 convenient for tracking down kernel bugs.  You need to run =git bisect
858 reset= to clear that state.  If you're nervous, you can save the state
859 on your own with =git bisect log > your-file=.
860
861 ** Automatic CCs with =git send-email=
862
863 The Linux kernel and Git mailing list (and other projects) prefer
864 patch submissions via email (vs. pull requests), so that everyone can
865 make line-by-line comments on the submissions before the patches are
866 committed to the main development repositories.  The Git commands that
867 facilitate this technique are =format-patch=, =send-email=, and =am=.
868 Here's how things will usually work.  We'll start off following the
869 patch developer.  It saves typing in the long run if you configure
870 some defaults first:
871
872     : $ git config --global user.name "John Doe"
873     : $ git config --global user.email jdoe@invalid.com
874     : $ git config --global user.signingkey 0x0123456789ABCDEF
875     : $ git config --global format.thread true
876     : $ git config --global sendemail.cc-cmd ~/bin/git-cc
877     : $ git config --global sendemail.aliasesfile ~/.mutt/aliases
878     : $ git config --global sendemail.aliasfiletype mutt
879     : $ echo 'alias git-list git@vger.kernel.org' >> ~/.mutt/aliases
880
881 The =git-cc= command is a slick, =git-blame=\-based script by [[http://felipec.wordpress.com/2009/10/25/git-send-email-tricks/][Felipe
882 Contreras]] ([[http://gist.github.com/218093][gist]]).
883
884 Checkout the source, and start your development branch:
885
886     : $ git clone git://github.com/gitster/git.git
887     : $ cd git
888     : $ git config sendemail.to git-list
889     : $ git checkout -b dev/my-feature
890
891 Make your changes:
892
893     : $ emacs gitweb/gitweb.perl
894     :   (hack, hack, hack, …)
895     : $ git commit -am "gitweb: refactor …"
896
897 If upstream has moved on, rebase your changes onto the new trunk:
898
899     : $ git checkout master
900     : $ git pull
901     : $ git rebase master dev/my-feature
902
903 and mail them upstream:
904
905     : $ git send-email --signoff --annotate --cover-letter origin/master
906
907 You can record your patches for comparison with:
908
909     : $ git format-patch --output-directory patch-my-feature-v1 origin/master
910
911 When you hear back with comments on how to improve the patch set, make
912 the appropriate changes with:
913
914     : $ git checkout dev/my-feature
915     : $ git rebase -i
916     : $ git checkout master
917     : $ git pull
918     : $ git rebase master dev/my-feature
919
920 Then send off an updated version:
921
922     : $ git format-patch --output-directory patch-my-feature-v2 origin/master
923     : $ git diff -ru patch-my-feature-v{1,2} > /tmp/diff-for-cover-letter
924     : $ git send-email --signoff --annotate --cover-letter --subject-prefix 'PATCH v2' origin/master
925
926 See =gitworkflows(7)= for other good ideas.
927
928 ** Signing commits with GPG
929
930 Since version 1.7.9, Git can sign commits with =-S=.
931
932     : $ git commit -S -m 'Look, a signed commit!'
933     : $ git log --show-signature
934
935 One more reason to be running =gpg-agent=.
936
937 ** Fun with =git notes=
938
939 *** Creating and showing notes
940
941 Say you have a repository
942
943     : $ git log
944     : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
945     : Author: W. Trevor King <wking@tremily.us>
946     : Date:   Tue Sep 4 13:21:28 2012 -0400
947     : 
948     :     b
949     : 
950     : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
951     : Author: W. Trevor King <wking@tremily.us>
952     : Date:   Tue Sep 4 13:21:18 2012 -0400
953     : 
954     :     a
955
956 You can attach a single note file (per note namespace) to each commit.
957
958     : $ git notes add -m 'note on commit a' HEAD^
959     : $ git notes add -m 'note on commit b' HEAD
960     : $ git notes
961     : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
962     : 068f07ddec5dfe0a8f93721acbdd7da87dd94db2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
963
964 The output format is =<note blob sha> <commit sha>=.  You can dump a
965 note by hand,
966
967     : $ git show 068f07
968     : note on commit a
969
970 or show the note associated with an object,
971
972     : $ git notes show HEAD
973     : note on commit b
974
975 or show the notes in a log.
976
977     : $ git log --notes
978     : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
979     : Author: W. Trevor King <wking@tremily.us>
980     : Date:   Tue Sep 4 13:21:28 2012 -0400
981     : 
982     :     b
983     : 
984     : Notes:
985     :     note on commit b
986     : 
987     : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
988     : Author: W. Trevor King <wking@tremily.us>
989     : Date:   Tue Sep 4 13:21:18 2012 -0400
990     : 
991     :     a
992     : 
993     : Notes:
994     :     note on commit a
995
996 *** Altering notes
997
998 You can append new content to an existing note,
999
1000     : $ git notes append -m 'more notes on commit a' HEAD^
1001     : $ git notes show HEAD^
1002     : note on commit a
1003     : 
1004     : more notes on commit a
1005
1006 or spawn your =EDITOR= to make changes.
1007
1008     : $ EDITOR='sed -i "s/more/many/"' git notes edit HEAD^
1009     : $ git notes show HEAD^
1010     : note on commit a
1011     : 
1012     : many notes on commit a
1013
1014 *** Removing notes
1015
1016 You can remove notes.
1017
1018     : $ git notes remove HEAD^
1019     : Removing note for object HEAD^
1020     : $ git notes
1021     : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
1022
1023 *** Note namespaces
1024
1025 Git notes have their own references in =refs/notes/...=.
1026
1027     : $ git notes get-ref
1028     : refs/notes/commits
1029
1030 You can use other namespaces besides =commits=.
1031
1032     : $ git notes --ref wtk get-ref
1033     : refs/notes/wtk
1034     : $ git notes --ref wtk add -m 'wtk note' HEAD
1035     : $ git log --notes=wtk
1036     : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
1037     : Author: W. Trevor King <wking@tremily.us>
1038     : Date:   Tue Sep 4 13:21:28 2012 -0400
1039     : 
1040     :     b
1041     : 
1042     : Notes (wtk):
1043     :     wtk note
1044     : 
1045     : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1046     : Author: W. Trevor King <wking@tremily.us>
1047     : Date:   Tue Sep 4 13:21:18 2012 -0400
1048     : 
1049     :     a
1050
1051 *** Showing notes in the log
1052
1053 If you want to show multiple namespaces in a single log, just keep
1054 adding =--notes= arguments.
1055
1056     : $ git log --notes=wtk --notes
1057     : commit 56db93aebad496c8ec28df0c4c90bed99da57e94
1058     : Author: W. Trevor King <wking@tremily.us>
1059     : Date:   Tue Sep 4 13:21:28 2012 -0400
1060     : 
1061     :     b
1062     : 
1063     : Notes:
1064     :     note on commit b
1065     : 
1066     : Notes (wtk):
1067     :     wtk note
1068     : 
1069     : commit 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1070     : Author: W. Trevor King <wking@tremily.us>
1071     : Date:   Tue Sep 4 13:21:18 2012 -0400
1072     : 
1073     :     a
1074
1075 *** Searching notes
1076
1077 You can search through notes for regular expressions.
1078
1079     : $ git grep wtk refs/notes/wtk
1080     : refs/notes/wtk:56db93aebad496c8ec28df0c4c90bed99da57e94:wtk note
1081
1082 The output format here is =<ref>:<commit sha>:<matching line>=.
1083
1084 *** The note branch
1085
1086 Because the notes are stored in their own branch, they have their own
1087 commit history.
1088
1089      : $ git log -p notes/commits
1090     : commit 0625b737c1dd340122478d8e6ae1fe5f8d8ce183
1091     : Author: W. Trevor King <wking@tremily.us>
1092     : Date:   Tue Sep 4 13:25:24 2012 -0400
1093     : 
1094     :     Notes removed by 'git notes remove'
1095     : 
1096     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1097     : deleted file mode 100644
1098     : index 866bab5..0000000
1099     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1100     : +++ /dev/null
1101     : @@ -1,3 +0,0 @@
1102     : -note on commit a
1103     : -
1104     : -many notes on commit a
1105     : 
1106     : commit b046ea813f3e5324e0910da5e60b3aa933aee2ff
1107     : Author: W. Trevor King <wking@tremily.us>
1108     : Date:   Tue Sep 4 13:24:55 2012 -0400
1109     : 
1110     :     Notes added by 'git notes edit'
1111     : 
1112     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1113     : index 975b66d..866bab5 100644
1114     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1115     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1116     : @@ -1,3 +1,3 @@
1117     :  note on commit a
1118     :  
1119     : -more notes on commit a
1120     : +many notes on commit a
1121     : 
1122     : commit d6f6b1e5c8832552e807bcab723e6eaf07d5e5de
1123     : Author: W. Trevor King <wking@tremily.us>
1124     : Date:   Tue Sep 4 13:24:16 2012 -0400
1125     : 
1126     :     Notes added by 'git notes append'
1127     : 
1128     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1129     : index 068f07d..975b66d 100644
1130     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1131     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1132     : @@ -1 +1,3 @@
1133     :  note on commit a
1134     : +
1135     : +more notes on commit a
1136     : 
1137     : commit 76e670903fcf038b602190a2e0314b265d5a34cf
1138     : Author: W. Trevor King <wking@tremily.us>
1139     : Date:   Tue Sep 4 13:22:28 2012 -0400
1140     : 
1141     :     Notes added by 'git notes add'
1142     : 
1143     : diff --git a/56db93aebad496c8ec28df0c4c90bed99da57e94 b/56db93aebad496c8ec28df0c4c90bed99da57e94
1144     : new file mode 100644
1145     : index 0000000..bb511b3
1146     : --- /dev/null
1147     : +++ b/56db93aebad496c8ec28df0c4c90bed99da57e94
1148     : @@ -0,0 +1 @@
1149     : +note on commit b
1150     : 
1151     : commit 62b129c10cdfc8ec9f9d204dac04a5cf0562dffe
1152     : Author: W. Trevor King <wking@tremily.us>
1153     : Date:   Tue Sep 4 13:22:21 2012 -0400
1154     : 
1155     :     Notes added by 'git notes add'
1156     : 
1157     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1158     : new file mode 100644
1159     : index 0000000..068f07d
1160     : --- /dev/null
1161     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1162     : @@ -0,0 +1 @@
1163     : +note on commit a
1164
1165 You can checkout the note branch just like any other branch.
1166
1167     : $ git checkout notes/commits
1168
1169 Where you will find one file for each note, where the filename is the
1170 hash of the object that the note is about.
1171
1172     : $ ls
1173     : 56db93aebad496c8ec28df0c4c90bed99da57e94
1174     : $ cat 56db93aebad496c8ec28df0c4c90bed99da57e94 
1175     : note on commit b
1176
1177 You can do all your usual manipulations in the note branch, merging,
1178 rebasing, updating refs, etc.
1179
1180     : $ git update-ref refs/notes/commits b046ea
1181     : $ git notes
1182     : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
1183     : 866bab52944f009b3f92c61beea7a8a7fad0e0a2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1184
1185 *** Adding notes to non-commit objects
1186
1187 There's no reason you need to limit your notes to commits.  However,
1188 you'll need the hash for the object you're tagging.  Here's how you
1189 can get a hash for a file:
1190
1191     : $ git hash-object a
1192     : 78981922613b2afb6025042ff6bd878ac1994e85
1193
1194 Alternatively, you can list all the files in a directory.
1195
1196     : $ ls-tree HEAD^{tree}
1197     : 100644 blob 78981922613b2afb6025042ff6bd878ac1994e85    a
1198     : 100644 blob 61780798228d17af2d34fce4cfbdf35556832472    b
1199
1200 Then attach your note to the object directly.
1201
1202     : $ git notes add -m 'note on blob a' 789819
1203     : $ $ git notes show $(git hash-object a)
1204     : note on blob a
1205
1206 *** Merging notes
1207
1208 **** Naming remote note references
1209
1210 It's a good idea to place all of your note references under
1211 =refs/notes=, because the current (2012-09-04) implementation of
1212 =expand_notes_ref= in =git/notes.c= is:
1213
1214     : void expand_notes_ref(struct strbuf *sb)
1215     : {
1216     :   if (!prefixcmp(sb->buf, "refs/notes/"))
1217     :     return; /* we're happy */
1218     :   else if (!prefixcmp(sb->buf, "notes/"))
1219     :     strbuf_insert(sb, 0, "refs/", 5);
1220     :   else
1221     :     strbuf_insert(sb, 0, "refs/notes/", 11);
1222     : }
1223
1224 This means that:
1225
1226     : refs/notes/commits → refs/notes/commits
1227     : notes/commits      → refs/notes/commits
1228     : commits            → refs/notes/commits
1229
1230 But:
1231
1232     : refs/remotes/origin/notes/commits → refs/notes/refs/remotes/origin/notes/commits
1233
1234 which is probably not what you wanted.
1235
1236 For more details about why this is the case, read [[http://thread.gmane.org/gmane.comp.version-control.git/160503][this thread]].
1237
1238 **** Fast forward merges
1239
1240 You can check out the note branch and pull/push/merge just like any
1241 other branch, but there is also a user interface for merging notes
1242 without bothering to checkout the note branch.  To see this in action,
1243 we'll need to clone our repo.
1244
1245     : $ cd ..
1246     : $ git clone repo-a repo-b
1247     : Cloning into 'repo-b'...
1248     : done.
1249     : $ cd repo-b
1250
1251 Git doesn't fetch (or push) notes by default, so we'll have to add a
1252 refspec.
1253
1254     : $ git config --add remote.origin.fetch '+refs/notes/*:refs/notes/remotes/origin/*'
1255     : $ git fetch
1256     : From ../repo-a
1257     :  * [new ref]         refs/notes/commits -> refs/notes/remotes/origin/commits
1258     :  * [new ref]         refs/notes/wtk -> refs/notes/remotes/origin/wtk
1259
1260 Alrighty, let's make those note's our own.
1261
1262     : $ git notes merge origin/notes/commits
1263     : fatal: Cannot merge empty notes ref (refs/notes/origin/notes/commits) into empty notes ref (refs/notes/commits)
1264
1265 Hmm, looks like the initial commit may be troublesome.  Let's adopt
1266 the current remote state.
1267
1268     : $ git update-ref refs/notes/commits refs/notes/remotes/origin/commits
1269     : $ git notes
1270     : bb511b3526c2300251c482b6f408248c83f22bff 56db93aebad496c8ec28df0c4c90bed99da57e94
1271     : a4c2f4dcfdb7d547bc303282f2678581a9ebf35f 78981922613b2afb6025042ff6bd878ac1994e85
1272     : 866bab52944f009b3f92c61beea7a8a7fad0e0a2 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1273
1274 And make some changes.
1275
1276     : EDITOR='sed -i "N;/\nmany/s/\nmany/extra/;P;D"' git notes edit HEAD^
1277     : git notes show HEAD^
1278     : note on commit a
1279     : extra notes on commit a
1280
1281 Now go back to the original repo and fetch the changes.
1282
1283     : $ cd ../repo-a
1284     : $ git remote add repo-b ../repo-b
1285     : $ git config --add remote.repo-b.fetch '+refs/notes/*:refs/notes/remotes/repo-b/*'
1286     : $ git fetch repo-b
1287     : remote: Counting objects: 5, done.
1288     : remote: Compressing objects: 100% (2/2), done.
1289     : remote: Total 3 (delta 1), reused 0 (delta 0)
1290     : Unpacking objects: 100% (3/3), done.
1291     : From ../repo-b
1292     :  * [new branch]      master     -> repo-b/master
1293     :  * [new ref]         refs/notes/commits -> refs/notes/remotes/repo-b/commits
1294     : $ git diff notes/commits notes/remotes/repo-b/commits
1295     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1296     : index 866bab5..710e3e0 100644
1297     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1298     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1299     : @@ -1,3 +1,2 @@
1300     :  note on commit a
1301     : -
1302     : -many notes on commit a
1303     : +extra notes on commit a
1304
1305 Merge.
1306
1307     : $ git notes merge -v remotes/repo-b/commits
1308     : Fast-forward
1309
1310 **** Resolving conflicts
1311
1312 Set up conflicting changes.
1313
1314     : repo-a$ EDITOR='sed -i "s/extra/tons of/"' git notes edit HEAD^
1315     : repo-b$ EDITOR='sed -i "s/extra/lots of/"' git notes edit HEAD^
1316     : repo-b$ git fetch
1317     : remote: Counting objects: 5, done.
1318     : remote: Compressing objects: 100% (2/2), done.
1319     : remote: Total 3 (delta 1), reused 0 (delta 0)
1320     : Unpacking objects: 100% (3/3), done.
1321     : From ../repo-a
1322     :    69e6240..bf61bfc  refs/notes/commits -> refs/notes/remotes/origin/commits
1323     : repo-b$ git diff refs/notes/commits refs/notes/remotes/origin/commits
1324     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1325     : index 0808976..b847e1d 100644
1326     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1327     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1328     : @@ -1,2 +1,2 @@
1329     :  note on commit a
1330     : -lots of notes on commit a
1331     : +tons of notes on commit a
1332
1333 Try to merge =repo-a= from =repo-b=.
1334
1335     : $ git notes merge refs/notes/remotes/origin/commits
1336     : Auto-merging notes for 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1337     : CONFLICT (content): Merge conflict in notes for object 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1338     : 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'.
1339     : $ ls .git/NOTES_MERGE_WORKTREE/
1340     : 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1341     : $ cat .git/NOTES_MERGE_WORKTREE/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1342     : note on commit a
1343     : <<<<<<< refs/notes/commits
1344     : lots of notes on commit a
1345     : =======
1346     : tons of notes on commit a
1347     : >>>>>>> refs/notes/remotes/origin/commits
1348     : $ emacs .git/NOTES_MERGE_WORKTREE/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1349     : <edit as you see fit>
1350     : $ git notes merge --commit
1351     : $ git notes show HEAD^
1352     : note on commit a
1353     : zounds of notes on commit a
1354
1355 You can also set some useful merge strategies.  Lets go back and try
1356 the merge again.  First, undo the merge
1357
1358     : $ git update-ref refs/notes/commits refs/notes/commits^
1359     : $ git diff refs/notes/commits refs/notes/remotes/origin/commits
1360     : diff --git a/84b126ce36567260bef8d0bbea03d426c9b7aa6d b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1361     : index 0808976..b847e1d 100644
1362     : --- a/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1363     : +++ b/84b126ce36567260bef8d0bbea03d426c9b7aa6d
1364     : @@ -1,2 +1,2 @@
1365     :  note on commit a
1366     : -lots of notes on commit a
1367     : +tons of notes on commit a
1368
1369 Now merge with a particular strategy.
1370
1371     : $ git notes merge --strategy=cat_sort_uniq refs/notes/remotes/origin/commits
1372     : Concatenating unique lines in local and remote notes for 84b126ce36567260bef8d0bbea03d426c9b7aa6d
1373     : $ git notes show HEAD^
1374     : lots of notes on commit a
1375     : note on commit a
1376     : tons of notes on commit a
1377
1378 There are more details about the available merge strategies in =git
1379 notes --help=.
1380
1381 * Troubleshooting
1382 ** Git commit hangs with no output
1383
1384 You probably corrupted something in =.git=.
1385
1386     : $ git gc
1387     : $ git fsck
1388
1389 fixed the problem for me.
1390
1391 ** Conflicting merge
1392   :PROPERTIES:
1393   :CUSTOM_ID: conflicting-merge
1394   :END:
1395
1396 =git pull= or =git merge= aborts with =merge-failed= or some such.
1397 This leaves your checked out branch in a state where
1398
1399     : $ git diff
1400
1401 shows the merge difficulties.  You can either [[#abort-merge][abort the merge]], or
1402 [[#hand-merge][merge by hand]].
1403
1404 *** Abort the merge
1405   :PROPERTIES:
1406   :CUSTOM_ID: abort-merge
1407   :END:
1408
1409     : $ git reset --hard HEAD
1410
1411 *** Merge by hand
1412   :PROPERTIES:
1413   :CUSTOM_ID: hand-merge
1414   :END:
1415
1416 Edit the marked packages as you see fit.  Then let Git know you've
1417 accepted your changes with either
1418
1419     : $ git update-index
1420
1421 or
1422
1423     : $ git add CONFLICT_FILE
1424
1425 Then commit with
1426
1427     : $ git commit -a