-
Notifications
You must be signed in to change notification settings - Fork 0
/
git
1280 lines (1081 loc) · 59.7 KB
/
git
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Git resources:
https://github.com/blog/2019-how-to-undo-almost-anything-with-git
(well-meaning article https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified, maybe good but this reference is a much better recipe book)
man gittutorial
https://www.kernel.org/pub/software/scm/git/docs/everyday.html
http://git-scm.com/book/en/Git-Basics-Viewing-the-Commit-History
looks like this is part of a pretty good book!
http://osteele.com/posts/2008/05/my-git-workflow
http://robotics.usc.edu/~ampereir/wordpress/?p=487
http://nvie.com/posts/a-successful-git-branching-model/
http://www.sonassi.com/knowledge-base/our-magento-git-guide-and-work-flow/
(in particular "quick and dirty restore points")
http://randyfay.com/content/rebase-workflow-git
http://randyfay.com/node/103
http://andyjeffries.co.uk/articles/25-tips-for-intermediate-git-users
http://steveko.wordpress.com/2012/02/24/10-things-i-hate-about-git/
http://think-like-a-git.net/
http://schacon.github.io/git/howto-index.html (with link to linus's "revert a faulty merge")
https://git.wiki.kernel.org/index.php/Git_FAQ
http://nuclearsquid.com/writings/git-tricks-tips-workflows/
really good advice
TODO: check out his git-wtf script
http://www.fini.net/v/RichmondPM/JohnLundinDevel
really good overview of git and other version control systems, with more links
http://blogs.gnome.org/newren/2007/12/08/limbo-why-users-are-more-error-prone-with-git-than-other-vcses/
recommends, for common use:
"git diff HEAD" instead of "git diff" (shows diffs from head whether marked for commit or not)
"git commit -a" instead of "git commit" (automatically adds all changes to tracked files)
http://marklodato.github.io/visual-git-guide/index-en.html
http://onlywei.github.io/explain-git-with-d3/
awesome!!! great exercises!
brilliant github visualization: http://ghv.artzub.com/
(unfortunately it doesn't recognize my .prejava files as source?)
TODO: check out "vim git gutter"
Awesome interactive cheatsheet:
http://www.ndpsoftware.com/git-cheatsheet.html
Huh? slideshow? http://sbecker.github.com/intro_to_git/#29
Customizations and aliases I currently use:
Tcsh aliases:
# Current git aliases to make my life easier... subject to change.
# NOTE no --color is given here (for some commands like git-status,
# there isn't even an option)--
# we assume "git config --global color.ui auto" has been run instead)
alias g git
alias gc git checkout
alias gb git branch
alias gs git status
alias gd git difftool -y
alias gl 'git log --graph --decorate --date-order --stat --summary'
# note, the --stat --summary foils other things like --oneline
alias gl0 'git log --graph --decorate --date-order --oneline `cd .git/refs/heads && /bin/ls | grep -v .-work` --'
# I guess the -- was because I was using this and appending branch names?
# but it keeps me from being able to add other args like -10, so I don't think I like it...
alias gl1 'git log --graph --decorate --date-order --oneline --branches=*'
Other useful options:
-<n> limit to last n
--all - show more of the graph (start with all refs)
FETCH_HEAD (not included in --all, and not labeled in output for some reason... although usually same as origin/master or something)
--oneline - much easier to get sense of entire graph this way!
--pretty=[oneline|short|medium|full|fuller] (default is medium)
Customizations (mostly from http://nuclearsquid.com/writings/git-tricks-tips-workflows/):
# Allow all Git commands to use colored output, if possible:
git config --global color.ui auto
# Allow git diff to do basic rename and copy detection:
git config --global diff.renames copies
# Tell git diff to use mnemonic prefixes (i[ndex], w[ork tree], c[ommit], o[bject]) instead of the standard a and b notations, where appropriate
git config --global diff.mnemonicprefix true
# Always show a diffstat at the end of a merge:
git config --global merge.stat true
- Put a "git" wrapper in my ~/bin, see below
(but I think probably the paging problem it's working around has been fixed)
- throw the git aliases lg(=lg1) and lg2 in my ~/.gitconfig, see http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs,
they look great.
But added --date-order to both of them.
TODO: the tag colors aren't as nice and varied as in the default-- should figure out how to tweak them
NICE GIT LOG ALIASES:
Various people have aliases for formatting that looks great.
http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs
Suggests the following:
[alias]
lg1 = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all
lg = !"git lg1"
- but add --date-order
- and change "bold yellow" to "auto" (to get HEAD in bold cyan, master in bold green, remote branches in bold red, tags in bold yellow)
http://stackoverflow.com/questions/15458237/git-pretty-format-colors
git log --graph --pretty=format:'%C(magenta)%h%Creset -%C(red)%d%Creset %s %C(dim green)(%cr) %C(cyan)<%an>%Creset' --abbrev-commit
- but add --all --date-order
http://sweetme.at/2013/09/13/git-logs-with-color/
Suggests the following:
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
- but add --all --date-order
http://blog.n.vasilak.is/post/51402193733/playing-with-git-log-pretty-format-color
Suggests the following:
lg = log --graph --pretty=format:'%C(yellow)%h\t[%ad]%C(reset) -%C(yellow) %d% C(reset) %s %C(green)(%cr) %C(blue)%an %C(reset)' --abbrev-commit --date=short
git log --graph --pretty=format:'%C(yellow)%h\t[%ad]%C(reset) -%C(yellow)%d%C(reset) %s %C(green)(%cr) %C(blue)%an %C(reset)' --abbrev-commit --date=short
To see available colors, start with this answer from the git-pretty-format-colors answer:
git log --pretty=format:"%Credred%Creset %Cgreengreen%Creset %C(Yellow)yellow%Creset %Cblueblue%Creset %C(magenta)magenta%Creset %C(cyan)cyan%Creset %C(white)white%Creset"
Available colors: black red green yellow blue magenta cyan white normal
Available modifiers: bold dim ul blink reverse
Observations:
- blink doesn't work in gnome-terminal (it works in konsole though :-( )
- on konsole, all the normal colors are same as dim colors
- and dim cyan is same as cyan even on gnome-terminal :-(
Is there a nice command to exercise a lot of this?
Let's put one together for the colors at least, in bash:
git log -1 --format="`for color in black red green yellow blue magenta cyan white normal; do for modifier in "bold " "" "dim "; do echo -n "%C($modifier$color)$modifier$color %Creset "; done; echo; done`"
Note can also do full matrix of foreground and background; not interesting enough to polish:
git log -1 --format="`
for fgcolor in normal black red green yellow blue magenta cyan white; do \
for fgmodifier in "bold " "" "dim "; do \
for bgcolor in normal black red green yellow blue magenta cyan white; do \
echo -n "%C($fgcolor $bgcolor $fgmodifier)$fgmodifier$fgcolor on $bgcolor%Creset "; done; echo; done; done`"
Hmm and maybe full 24-bit colors available? See https://jpace.wordpress.com/2013/05/04/extended-colors-with-git/
Yeah instead of a color name, can use an ansi code... which is two numbers!? fg and bg.
one of them is, if r,g,b are values in [0..5]: 6*16 + 36*r + 6*g + b !? and what's the other one?
Holy moly that's arcane! And not quite it, either... need to experiment.
So let's see, what do *I* like?
I want to use the default colors as much as possible but add stuff like everyone else does.
Except the "yellow" for the abbreviated hashes looks yucky, so maybe change that to something like "magenta" or "bold black".
Actually I think I really like the format and color scheme of http://stackoverflow.com/questions/15458237/git-pretty-format-colors;
the only thing I'd change is:
- add --all --date-order
- change red to auto for the %d
- remove the " - ", yeah it's nice but it takes up precious real estate
- don't need the --abbrev-commit since using %h explicitly
- change %an to %ae since email addr is more interesting to me at the moment
(there's just one person making commits, but submitting from various email addrs)
So my alternative to --decorate --oneline is the following --format:
git log --graph --format='%C(magenta)%h%C(reset) -%C(auto)%d%C(reset) %s %C(dim green)(%cr) %C(cyan)<%ae>%C(reset)' --date-order --all -15
(Note, most people would probably use %an "author name" instead of %ae "author email"
but at the moment I'm dealing with repos for which I'm the only committer
and I commit from multiple email addrs, so that's more interesting)
TODO: check out nice "git log" aliases in http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs, they look great
TODO: sort out how I want to be doing this. I don't think I like aliases
since they are hard to port. Maybe sticking commands in ~/bin instead?
The "git log" I'm currently using most is:
git log --graph --dec --date-order --all --oneline
BEST PRACTICES:
- empty commit at root of repo, for various reasons
having to do with the fact that without it you can't do certain
rebase operations at the root, see:
http://stackoverflow.com/questions/645450/git-how-to-insert-a-commit-as-the-first-shifting-all-the-others
mkdir myNewRepo
cd myNewRepo
git init
git commit --allow-empty -m "Initial empty commit"
- when creating a new branch, I like to always make an empty commit:
git checkout A
git checkout -b B # short for: git branch B A; git checkout B
git commit --allow-empty -m "Create branch 'B' from 'A'"
this makes 'git log --graph' much easier to read!
Also, I'm thinking, always use precisely that format;
then it can be parsed by automated tools to make swimlanes.
then maybe future automated tools that make swimlanes can use it.
Also when merging back, don't fast-forward:
git checkout A
git merge --no-ff B
git branch -d B
that will make the default comment "Merge branch 'simplify_listeners'"
which is good. (And during edit or in -m flag, add "back into 'A'" to make it even better.)
- TODO: sometimes I'll have a bunch of commits that I later decide
should have been done in a topic/feature branch
(with the appropriate "Create branch 'B' from 'A'" initial empty commit,
and the "Merge branch 'B' back into 'A'" if the work is done).
Make a recipe for making that happen.
In fact, could even theoretically do that for commits
that aren't sequential or in order, since git can reorder.
Not sure what the chances of success are though.
Maybe this is one of the things that can be done with "git rebase -i"? Not sure.
- when deleting a branch with -D, or resetting it,
if you don't want it to disappear, tag it first:
git tag myBranch-about-to-delete-2013-01-01
NOTE: I'm probably not understanding or using tags correctly.
Evidently you have to say "git push --tag" if you want to push it.
And, deletion of the tag or branch doesn't get pushed. Confusing,
if I want all my repos to be in sync.
(Hmm I guess "push --mirror" does this... but, that's scary!
Did it anyway. And really confused :-( )
Ouch! Creating a tag causes github to create a release!? Way confusing!
Maybe it's adequate to just do the marker commits mentioned previously,
instead of this.
- Don't use aliases for branches. it breaks various scripts
that aren't expecting the output of "git branch" to contain that stuff.
- breaks git-rebase-all (that guy's script)
- gives useless extra columns in "git show-branch"
- Never use -n thinking it will mean --dry-run.
It means that in some tools but not others, and it will bite you.
THINGS IT WOULD BE NICE TO HAVE A HELPER WRAPPER FOR MAYBE:
- git diff has --word-diff but it still spews way more than it needs to a lot. would be nice to have it even more fine-grained, on a char level even.
- the stats from "git log --stat" are cool but a bit brain dead,
can't they show changed lines in yellow, in addition to deleted lines in red
and added lines in green?
See:
http://stackoverflow.com/questions/9933325/is-there-a-way-of-having-git-show-lines-added-lines-changed-and-lines-removed
It's a nice little bash fragment but:
- the patterns aren't quite right, e.g. when adding a line that begins with spaces
- need to take it a step further and produce the little stat picture.
Instead of:
NEWS | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
we'd have:
NEWS | 8 ++++!!--
1 files changed, 4 insertions(+), 2 changes (!), 2 deletions(-)
- is there a way to replace all git diff stat pictures with this? (git diff --stat, git log --stat, ...)
(hmm, I think it's using the "diffstat" program,
which, according to man page, is supposed to do this? is it broken or something?)
And see:
http://stackoverflow.com/questions/23927495/why-does-gits-diffstat-only-show-lines-that-have-been-added-deleted-but-not-lin
It's really weird that "man diffstat" and various git things seem to say we should see "!" sometimes,
but I never do??
NEED TO WRITE THE DAMN THING, OBVIOUSLY :-(
- swim lanes!!! devoted a whole section to this, below.
It is git's foremost deficiency, in my opinion.
- Pisses me off when quitting out of git log makes tcsh say "Broken Pipe" which makes the top line scroll
off the top of the terminal
(furthermore I have a precmd that prints an extra line on nonzero exit status,
further exacerbating the problem).
I made a little wrapper to avoid this:
#!/bin/bash
# Little wrapper for git.
#
# This is a quick hack to make "git log" not print "Broken pipe"
# nor provoke my precmd that prints a line when a command fails.
# Actually, do this with all git commands, not just log... most of them
# go through the pager and will have the same issue.
/usr/bin/git "$@"
status=$?
if [ "$status" = "141" ]; then
# empirically this is what happens when it dies due to broken pipe.
# turn it into exit status 0
status=0
fi
exit $status
(Problem never happened in bash, I don't think)
- I'm working on a clone of a central repository,
and I currently have about 10 topic branches
on top of my local master and each other.
Some of these topic branches are logically topics, containing code changes,
while others are just unions of various subsets of the topics.
(e.g. work = stuffNeededToMakeBuildWork + freedMemoryReadFix + newTest1 + newTest2 + sortRefactor + sortFix;
where sortFix is on top of sortRefactor)
Each time I pull from remote/master to local master,
I then have to rebase all of these individual topic branches,
using something like:
git rebase master topic1
git rebase master topic2
...
and then I blow away and re-create each of the "union" topic branches, e.g.
git branch -f -b union1248 master
git merge topic1 topic2 topic4 topic8
And for the case where I have one non-automatically-generated topic (sortFix)
on top of another (sortRefactor), I manually do something that gets them right again:
git tag sortRefactor-old sortRefactor # put a bookmark on the old sortRefactor
git rebase master sortRefactor # do first rebase
git rebase --onto sortRefactor sortRefactor-old sortFix # do second rebase, as explicitly as possible
git tag -d sortRefactor-old # delete the bookmark
Original:
* master
\
*---*---* sortRefactor
\
*---* sortFix
After pull:
*---*---*---* master
\
*---*---* sortRefactor
\
*---* sortFix
After tagging and "git rebase master sortRefactor":
*---*---*---* master
\ \
\ *---*---* sortRefactor
\
*---*---* sortRefactor-old
\
*---* sortFix
After "git rebase --onto sortRefactor sortRefactor-old sortFix":
*---*---*---* master
\ \
\ *---*---* sortRefactor
\ \
\ *---* sortFix
*---*---* sortRefactor-old
\
*---* (inaccessible)
(Possibly the second rebase could be done with just
"git rebase sortRefactor sortFix", but that relies
on it automagically figuring out which diffs
are shared between the two paths,
and I'm pretty sure that would be more likely to come out wrong--
better to be explicit since I know exactly which diffs I want to be applied).
I have a script that does all of the above,
hard-coded for the particular branch structure I'm keeping,
but it seems to me that this shouldn't be necessary...
shouldn't it be possible to automatically figure out
exactly what needs to be done after a pull?
I.e. master head got updated,
so all nodes downstream from the original master head
should get rebased to the new master head,
*in such a way that the new nodes are in the same relationship
to each other that the old nodes were.*
Is there a command to do that?
Was asked here, no good answer:
http://git.661346.n2.nabble.com/Q-rebasing-moving-a-whole-tree-not-just-one-branch-td6186003.html
seems to me that people should want to do this all the time, no?
Probably safest way to do it is make temp copies of each branch,
do the rebasing among all the temp copies,
then if it all works, reset all original branches to the temp copies
and delete the temp copies.
Oh wait... does this do it?
git rebase --root --preserve-merges
No it doesn't. I think root just refers
to past the first commit, which
wouldn't be expressible otherwise.
--preserver-merges seems to do it,
but only if everything culminates in one final commit.
So, what if I merge everything together
into one artificial commit,
and then do "git rebase --preserve-merges" on that?
Hmm, how bout this? https://github.com/nornagon/git-rebase-all/blob/master/git-rebase-all
AHA!
http://stackoverflow.com/questions/9407234/git-maintaining-many-topic-branches-on-a-frequently-moving-base
so, he's got his own tool for it??
https://github.com/nornagon/git-rebase-all
Hmm, making it into git, see some posts there... --rewrite-{refs,heads,tags}
Oh! It does exactly what I was thinking!
Hmm, it's foiled by my branch aliases... remove them, then it gets farther.
Fooey!
- Seems like whenever I change something,
I want my branches that depend on it (rebase, merge) to get updated.
Can I express this using a Makefile??
Or some other file expressing how branches should be automatically regenerated from other branches??
Hmm, maybe StGit is the thing? Not sure.
http://www.procode.org/stgit/
hmm, http://nuclearsquid.com/writings/git-tricks-tips-workflows/ says:
"I used to use this program quite a lot, but it has since been superseded with git rebase and git stash."
- show currently checked out branch in prompt or title?
- make a trivial little branch switcher?
just shows output of "git branch", single-click switches branches (using "git checkout")
also uses fam to notice when anything changes in the refs directory
SWIMLANES!
- git log graph is still wicked confusing (even with --date-order).
can I get exactly one dedicated column per branch?
hmm, I'm getting the feeling a branch is just a (moving) label for a commit...
so after it gets moved (via git reset), I lose the record of where it was before, is that right?
yeah, that's right :-(
I'm getting more of a handle on this, by tagging branch heads that I delete or move
and by making empty commits at the beginning of each branch (see BEST PRACTICES below)
hmm, git show-branch gives one column per branch...
that's *almost* what I want but not quite...
it's rather cluttered since it shows all branches
back to infinity in time, past when the branch was created... ?
maybe I can make something more intuitive?
Really I think I just want git log to allocate a "swim lane"
for each branch, I think? Various discussion the web refers to this
as a swimlane.
See this for maybe some more thoughts; their screenshots look nice:
https://confluence.atlassian.com/display/FISHEYE/Ordering+of+Branches+Important+When+Visualising+Git+Changesets
and theyr tutorial is full of great pictures, all of which have
swimlanes:
https://www.atlassian.com/git/tutorials/comparing-workflows
(argh! not any more! but http://justinhileman.info/article/changing-history/ seems to have some of what I remember)
and supposedly "github network view" tries to give swim lanes?
https://github.com/git/git/network
It's a pain though-- lots of bitching about it, see for example: http://subimage.com/blog/2011/08/30/github-your-network-graph-sucks/
- Lack of swimlanes just isn't okay. Perforce thinks in terms of the swimlanes
(what it calls "branches" but I'm not attached to that),
and its history visualization is simply *better* than git's--
trying to figure out what was done in what branch (swimlane) in git amounts
to fumbling around in the dark.
What exactly do I need to add to my git workflow to get back that essential
functionality?
Partial answers in my BEST PRACTICES section but it's still not okay.
tags? notes?
I think the correct answer is that every normal commit should be marked with the branch
it came from... I guess with a tag? is that feasible?
See http://jhw.dreamwidth.org/1868.html "Why i like mercurial more than git".
It talks about this and how git could be fixed.
Interesting passage:
"Look, I wasn't kidding when I said that you can do a round-trip conversion of a Git repository into and back out of Mercurial without losing any data. There's even a way to do that in the other direction as long as the Git commit logs adhere to the convention required my Mercurial for storing the branch name."
So... what is that convention?
TODO: ask!
Uh oh, I'm getting deja vu...
The feature in mercurial is called "named branches" which you can choose
to use or not. It also uses terminology like "embedded", that is,
the branch name is embedded in changeset metadata)
(and its "bookmarks" are like git branches). Does git
actually have something corresponding to mercurial's named branches now?
TODO: read this and the answer, thoroughly:
http://stackoverflow.com/questions/16466994/how-to-get-more-useful-branch-diagrams-in-git
It might actually explain the git rationale somewhat coherently.
SETTING UP DIFFTOOLS (work in progress):
First of all, there are many references on the web
to methods that create wrapper scripts such as "git-diff-wrapper"...
I think they *may* be obsolete? (but they take 7 args, does that make them
more versatile? hmm TODO check this out)
Progress trying various tools...
xxdiff is really a good simple merge tool, wish I had the equivalent:
select what I want from left and/or right, save merged, done.
Why is that hard??
Well actually it's not ideal, it doesn't know the concept of merge base...
can I maybe write a tool that's the best of everything?
Oh well, experimenting with various existing:
Beyond Compare:
Currently I have this in my ~/bin/git-diff-wrapper:
#!/bin/sh
# http://www.iokom.com/drupal/node/4
# diff is called by git with 7 parameters:
# path old-file old-hex old-mode new-file new-hex new-mode
#"/usr/bin/bcompare" "$2" "$5" | cat
# TODO: there's a program that converts between cyg paths and windows paths, right?
# /tmp/whatever -> c:/cygwin/tmp/whatever
lhs="c:/cygwin$2"
rhs="$5"
"/cygdrive/c/Program Files (x86)/Beyond Compare 3/BComp.exe" "$lhs" "$rhs" | cat
Result:
Good for diff
Sucks for merge.
Actually supposed to show 3 revs side by side? I only see 2 revs! Wtf?
TODO: get straight on exactly what I'm doing and what the other options are
TODO: can I integrate the diff tool into git diffing?
TODO: can I integrate the diff tool into git merging?
TODO: can I integrate the merge tool into git diffing?
TODO: can I integrate the merge tool into git merging?
p4merge:
- Part of p4v, I just installed it all.
- Had to run installer a second time and "repair" for it to appear
in "c:/Program Files/Perforce/p4merge.exe".
- Have to change "line ending type" preference to Unix (if that's what I want)
Result:
Seems ike it would be fairly nice and usable, except:
- when lots of diffs, scrolling the right-hand part gets all corrupt??
hmm can't reproduce it on subsequent run, maybe doesn't happen
very often?
- a bit hard to tell what's what after "select left" and then
a couple of mods
- hmm, there's a diffing mode that's somewhat similar to xxdiff--
just run it with 2 files, then hit "edit file in left pane"
or "edit file in right pane", allowing selectively pulling over stuff from other side... could be useful
TODO: can I integrate the diff tool into git diffing?
TODO: can I integrate the diff tool into git merging?
TODO: can I integrate the merge tool into git diffing?
TODO: can I integrate the merge tool into git merging?
TODO: Check out:
- everything they mention here:
http://stackroulette.com/stackoverflow/137102/undefined
- SourceGear DiffMerge? this says it may be decent: http://therightstuff.de/2009/01/28/Setting-Up-SourceGear-DiffMerge-With-Git.aspx
- araxis merge
TODO: get straight on how to allow different tool options and how to set up scripts for each one
- http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs -- super nice!
TODO: think about the possibility of a branch-specific README as suggested in http://stackoverflow.com/questions/2108405/branch-descriptions-in-git
TODO: check out qgit
CRLF ISSUES:
http://stackoverflow.com/questions/170961/whats-the-best-crlf-carriage-return-line-feed-handling-strategy-with-git#answer-10855862
which refers to this:
https://help.github.com/articles/dealing-with-line-endings/
and says this is required reading:
http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
The one with the cartoon:
http://stackoverflow.com/questions/20168639/git-commit-get-fatal-error-fatal-crlf-would-be-replaced-by-lf-in/20168775#20168775
QUESTIONS:
Q: picture of all diff options?
A: Simple one: https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged?noredirect=1&lq=1#answer-1587952
A little more complete:
https://marklodato.github.io/visual-git-guide/index-en.html#diff
Q: graphical git client? especially for log graph view.
PA:
https://git-scm.com/downloads/guis
subQ: What's easily available on ubuntu?
subPA: apt install git-all # which includes git-gui
wait wtf? can't expand the tree to more than 2 inches vertically??
ah, yes I can, it's obcure though. the bar in question is under the "Find ... commit containing:".
https://stackoverflow.com/questions/35723579/expanding-commit-history-in-gitk#answer-35724476
apt install gitk
ah, this is what `git gui` brings up when you select visualization
Q: what does "-m 1" (i.e. --mainline 1) etc. mean, in `git revert` ?
A: Apparently parents are numbered internally: first parent
was the branch being merged into, second parent was the branch
being merged into it.
If I'm not mistaken, `git log --graph` seems to always show
the first parent on the left, i.e. straight line downward,
and the second parent slanting down to the right.
Also can do either of these,
which includes the list of parents in order:
git cat-file -p 4a77
git show --pretty=raw 4a77
git show 4a77
Incidentally, if you've ever wondered why the graph looks like this (no slanted lines down and to the right from a commit):
*
|\
| *
| |\
| |/
|/|
* |
* |
|\|
| *
| *
| |\
| |/
|/|
* |
| *
|/
*
instead of like this, which seems like it would be simpler:
*
|\
| *
|/|
* |
* |
|\|
| *
| *
|/|
* |
| *
|/
*
This is why (so you can tell by looking at it which is parent 1 and which is parent 2).
Note that `git gui` does *not* do this, making it less useful!
Note that there *are* some cases when lines slant down and to left;
that is: "when the first parent fuses with another edge to its left":
https://stackoverflow.com/questions/20200226/how-to-understand-git-log-graph#answer-59147423
but in this case, the leftmost is still the first parent.
Q: fast-forwarding a branch without checking out?
A: As recommended in various places, if you want to fast-forward branch "follower"
to "leader", then instead of this
(which has several assumptions/restrictions and fragilities):
git checkout follower
get merge --ff-only leader
do one of the following instead (they are equivalent):
git fetch . leader:follower
# or...
git push . leader:follower
Explanation: `.` in this case is the current repo; so, in either case,
you're saying "update current repo with itself (i.e. do nothing),
followed by a fast-forward update of follower to leader if possible".
These are preferable to other ways of moving the `follower` ref
(such as `git branch -f follower leader` or
`git update-ref refs/head/follower leader`)
since they will simply fail, rather than doing something you didn't intend,
if you are mistaken about a fast-forward merge being possible or if you get
the syntax wrong (e.g. for update-ref, it's easy to mistakenly say `follower`
instead of `refs/head/follower`, creating a garbage ref).
Q: make a new branch from current uncommitted/unstaged changes?
A: git checkout -b <new-branch>
And then, as in BEST PRACTICES section, commit staged (which is nothing):
git commit --allow-empty -m "Create branch 'B' from 'A'"
Q: p4 filelog?
A: git log dl-fini.c
git log --color --graph --stat --summary --decorate --date-order
explanation of those options:
--color - use color
--graph - show the nice graph on the LHS
--stat - show added/deleted lines stats (but never changed lines, that I've ever seen...!?)
--summary - also show extended info such as creations, renames and mode changes.
(OUCH! when added to that guy's alias lg, it makes an extra blank line after each line!?)
--decorate - show ref names. essential!
--date-order - instead of some weird arbitrary topsort order or something
Q: p4 describe?
A: git show 28363b
Q: p4 describe -s?
Q: p4diff?
A: git show 28363b dl-fini.c
git difftool -y 59ba27a 28363b dl-fini.c
Q: how to suppress the list of possible difftools?
Q: diff against previous?
git difftool -y 28363b{^,} dl-fini.c
git difftool -y 28363b~{1,0} dl-fini.c
Q: where are ~ and ^ documented?
A: in "man gittutorial" or "man gitrevisions"
The basic usage is:
HEAD^ or HEAD~1 -- parent of HEAD
HEAD^^ or HEAD~2 -- grandparent of HEAD
HEAD^^^ or HEAD~3 -- great-grandparent of HEAD
etc.
In case of multiple parents:
HEAD^2 -- 2nd parent of HEAD
HEAD^^3 -- 3nd parent of 1st parent of HEAD
HEAD^4^ -- 1st parent of 4th parent of HEAD
HEAD~2^5 -- 5nd parent of grandparent of HEAD
See "man gitrevisions" for more control about which parent and stuff.
Q: p4annotate?
A: git blame dl-fini.c
git blame 28363b dl-fini.c
Q: p4 print -q? (at given commit)
A: git show head:path/to/file
(path must be relative to depo root,
not current dir??)
Q: gui?
A: gitk, git gui
Q: what's the difference between git fetch and git pull?
A: git pull = git fetch + git merge
(generally considered evil)
git pull --rebase = git fetch + git rebase
(generally considered good... but it changes history?)
(holy shit, see https://coderwall.com/p/jiswdq/let-s-all-take-a-moment-of-silence-git-pull-is-dead )
(I guess I need to completely understand that?? For now, using git pull I think,
at least for my private repos)
Q: remove untracked files?
Q: what the hell does --mirror mean in practice? what the hell is a bare repository in practice?
PA: bare seems to mean it doesn't have the working files
Q: backup?
PA: (this might not be quite right... weird that it mixes in the git directory with the contents...? maybe don't use --mirror? maybe don't use --bare? push --mirror seems to want bare, but I don't understand its logic. non-bare is nice since then I can actually see the files)
git remote -v # check existing remotes
git remote add --mirror=push backup /dept/rnd/home/dhatch/backup/glibc.git
git config --add alias.backup "push --mirror backup"
mkdir -p /dept/rnd/home/dhatch/backup/glibc.git
cd /dept/rnd/home/dhatch/backup/glibc.git
git init --bare # and if I append .git, all files go into there?? weird
Q: all right then, how to diff against a version in a remote repo? (e.g. the backup)
PA: hmm, these seem to talk about it, but it doesn't work:
http://stackoverflow.com/questions/1800783/compare-local-git-branch-with-remote-branch
http://stackoverflow.com/questions/5162800/git-diff-between-cloned-and-original-remote-repository
I tried:
git diff master backup/master
fatal: ambiguous argument 'backup/master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
Q: git status without untracked files?
A: git status --untracked-files=no
or, equivalently: git status -uno
--------------------
Subject: git question: diff against remote files?
If anyone here cares to admit to being knowledgeable about git,
I have a question for you.
I've created a git repo in /gtmp/r71c320/doNotRemove/dhatch/glibc/git/glibc,
by executing:
% mkdir -p /gtmp/r71c320/doNotRemove/dhatch/glibc/git
% cd !$
% git clone git://sourceware.org/git/glibc.git
Since this location doesn't get backed up automatically,
I created a second repo, mirroring the first,
in a directory that *does* get backed up:
% mkdir -p /dept/rnd/home/dhatch/backup/glibc.git
% cd /dept/rnd/home/dhatch/backup/glibc.git
% git init --bare
% cd /gtmp/r71c320/doNotRemove/dhatch/glibc/git/glibc
% git remote -v # check existing remotes
% git remote add --mirror=push backup /dept/rnd/home/dhatch/backup/glibc.git
% git config --add alias.backup "push --mirror backup"
Then, to back up my work every once in a while, I run "git backup",
which appears to be working correctly.
My question is, how do I diff files
against the ones in the backup repo?
I googled it and several sources seem to say the following should work,
for starters:
% git diff backup/master master
But it doesn't; it gives the following error:
fatal: ambiguous argument 'backup/master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
So, how do I get these diffs?
My backup repo is of limited usefulness to me if I can't diff against it.
Don
--------------------
Q: make a tmp branch to hold changes I don't mean to check in anywhere?
A: git branch tmp
Q: okay how do I make a branch from a particular commit?
A: git branch tmp <commit>
Q: dry run push/pull/fetch/merge?
PA: some discussion in http://stackoverflow.com/questions/3636914/how-can-you-see-what-you-are-about-to-push-with-git
also here: http://stackoverflow.com/questions/822811/differences-in-git-branches
see Eric Anderson's answer, seems like a nice way to try out the merge
in a throw-away branch
also this:
http://docs.mathjax.org/en/latest/installation.html
seems to imply that "git remote show origin"
is the dry run of "git pull origin",
which seems to be essentially correct.
I'm thinking "git fetch" perhaps doesn't strongly need a dry run? Could just do it,
it updates our picture of what remote looks like, without causing local damage...
right? It does have a --dry-run option though.
(With some weirdness though-- it gives two different outputs if you run it twice
in a row.)
WARNING: do *not* use -n thinking it means --dry-run; it doesn't!
(for fetch it means --no-tags, for merge it means --no-stat, for pull I have no
idea what it means, for push it *does* mean --dry-run-- don't use it!!)
Q: why is "git status" not showing files ending in .orig?
A: it's listed in .gitignore
Q: git log is coming out in baffling order, wtf?
A: Here's the deal.
- The --pretty=fuller output shows two dates: AuthorDate and CommitDate.
- AuthorDate is shown as simply Date in the normal output.
As shown in `git help log`:
- default ordering is reverse chronological (presumably by CommitDate?
not clear, but it doesn't matter since nothing's very interesting
to me without the graph, which means sort by topo first).
- --date-order means top first and then CommitDate order.
- --author-date-order means top first and then author date order.
- --topo-order means topo first, and then try to avoid interleaving
(which means show some stuff out of order).
- --graph presumably implies topo-order? unless overridden by
--date-order or --author-date-order?
Q: whoa, git log graph is still wicked confusing.
can I get exactly one dedicated column per branch?
(see IDEAS section)
Q: how to get git log to show the *whole* graph, with *all*
commits?
PA:
nothing on the web works; stuff without branches pointing at them aren't shown
(i.e. nodes that became inaccessible from any branch,
via "git reset" or "git branch -D")
http://think-like-a-git.net/epic.html
git log --oneline --abbrev-commit --branches=* --graph --decorate --color
or, in non-epic version, different but effectively the same):
git log --oneline --abbrev-commit --all --graph --decorate --color
For example:
mkdir scratch
cd scratch
git init
touch foo
git add foo
git commit -m "adding empty foo"
echo "appending a line to foo" >> foo
git commit foo -m "appending a line to foo"
git reset --hard HEAD^
This seems to work, but relies on the reflog entries,
which disappear if a "git gc" is done after 90 days:
git log --color --graph --oneline --decorate --all --date-order `git reflog | sed 's/ .*//'`
This may be a bit better, since it doesn't rely on the reflog:
git log --color --graph --oneline --decorate --all --date-order `git fsck --lost-found --no-reflogs | sed 's/.* //'`
ouch, but http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
says lost&found will be deleted by git gc??
git reflog expire --expire=now
git gc --prune=now
Yup, that branch is GONE. Wtf? That's scary.
Even if it's not reachable, it is history.
We never lose that stuff in perforce, right?
And it still *is* still in the raw data blobs, right??
Idea: whenever doing one of:
git branch -d
git reset
store it as a tag, e.g.
topicA-deleted-2013-01-01
yeah that works nicely I think!
Q: can I express "git log --branches=<all but *-work>" ?
A: not directly, I think... it's a glob pattern.
but the following works, assuming it's run from the root of the repo:
git log `cd .git/refs/heads && /bin/ls | grep -v .-work`
Q: can I switch to previous branch I was on?
A: git checkout -
also "@{-N}" for N-th last branch
Q: where's that stored?
PA: it's just using reflogs probably. (verify that)
Q: can I push and pop current branch?
Q: switching branches (using git checkout) updates the timestamps
on all files that differ between the two branches,
causing unnecessary building.
can I merge between branches without calling git checkout?
PA: there's some discussion here:
http://stackoverflow.com/questions/4156957/merging-branches-without-checkout
someone recommended doing the edits in a different repo from the builds.
also here: http://stackoverflow.com/questions/1402993/git-checkout-and-merge-without-touching-working-tree
see djpohly's answer, although I don't fully understand it yet.
Q: how to show all the diffs between two branches?
A: some discussion here: http://stackoverflow.com/questions/822811/differences-in-git-branches
git diff --name-status master..work
git diff --stat master..work
Q: how bout just a particular file, between two branches?
A: git diff --stat master:foo work:foo
Q: all right I just did a merge (actually rebase) that I totally didn't want,
by mistake. one branch now has a bunch of changed files
that shouldn't be changed. how to fix it?
A: git reset --hard? (not clear what that does)
git revert
(actually haven't tried them, I hadn't quite done what I thought I did)
Q: how to "p4 integ" or "p4 copy" files from one branch to another? or from a previous state?
PA: I don't understand this, but http://stackoverflow.com/questions/307579/how-do-i-copy-a-version-of-a-single-file-from-one-git-branch-to-another
seems to say:
git checkout otherbranch myfile.txt
git checkout otherbranch:otherfile myfile.txt
git checkout <rev> -- myfile.txt
argh, but that loses track of where it came from??
wait, see here I think:
http://andyjeffries.co.uk/articles/25-tips-for-intermediate-git-users
in the section "Resetting changes"
Q: branch aliases?
A:
git symbolic-ref refs/heads/m refs/heads/master
git symbolic-ref refs/heads/s refs/heads/stuffNeededToMakeTestsWork
git symbolic-ref refs/heads/f refs/heads/freedMemoryReadFix
git symbolic-ref refs/heads/d refs/heads/dlSortFiniFix
git symbolic-ref refs/heads/work refs/heads/dlSortFiniFix-work
git symbolic-ref refs/heads/w refs/heads/work
BUT beware! don't use the alias for "merge" commands,
the alias will show up in the commit message, confusing everyone!
If that happens, see "how to change a commit message"
Also, to delete one of these, just delete the file--
do NOT say "git branch -d w"... actually not sure what that does!
Q: how to change a commit message?
PA:
git commit --amend -c <commit ID>
general advice on web is "don't ever change history after you've pushed"... but,
maybe that's for the more-complicated commands that people suggested?
seems to work okay if do the above and then push (at least, to a mirror bare repo).
ARGH! that didn't actually work-- it created a new commit! fuck!
That's fine except that anything deriving from it isn't any more.
So, need to rebase the whole tree,
everything that came on top of master,
we want to now come after the new master.
Is here a rebase --tree option or something?
Actually need this in general, since I maintain a whole tree of stuff that depends on each other.
Q: woops! committed to the wrong branch!
A: git reset --hard <previous commit>
(back up any files first, not sure what will happen to them)
Q: diff committed against index?
A: git diff --cached <file>
Q: diff index against unstaged?
A: git diff <file>
Q: diff committed against unstaged?
A: git diff HEAD <file>
holy hell! so the picture is:
committed index/staged modified/unstaged
<--git diff --cached--> <--git diff-->
<---------------git diff HEAD <file>------------>
Q: how come sometimes when I have edited but not staged a file,
it lets me switch branches, but sometimes not?
A: it lets me switch if the two branches' versions
of the file are identical.
(sometimes it lets me switch anyway,
as long as there are no merge conflicts when switching)
Q: Okay say I've got a branch called branch12,
and I want to split it into two branches branch1 and branch2
(their diffs from master don't conflict... branch1's changes
are to completely different files from branch2's).
Okay say I've got a branch called AB,
and I want to split it into two branches A and B
(their diffs from master don't conflict... A's changes
are to completely different files from B's).
1 AB
/
0 master
Method 1:
I first create branch A from AB:
git checkout AB