-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathgit.cli.txt
1371 lines (1181 loc) · 87.5 KB
/
git.cli.txt
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 ┃
┗━━━━━━━━━┛
VERSION ==> #Git 1.9.1
SUMMARY ==> # - basic:
# - init|clone
# - config, .gitattributes
# - references:
# - HEAD@{NUM}, ORIG_HEAD: last positions
# - COMMIT^[2], COMMIT~NUM, COMMIT^{/REGEXP}: parent commits
# - tag: versions
# - branches:
# - branch
# - git branch LBRANCH LRBRANCH: sets upstream while creating
# - checkout: moves around
# - merge, rebase, cherry-pick
# - problem fixing:
# - revert: undo commit
# - commit --amend
# - rebase -i
# - reset: erase history / go back
# - filter-branch
# - staging area:
# - status|add|reset|rm|mv|commit
# - stash
# - info:
# - log, show
# - shortlog
# - describe: where are we version-wise
# - bisect
# - maintainance:
# - clean: remove untracked files
# - fsck
# - remotes: remote, fetch, push, pull
# - patches: diff, apply
# - email: format-patch, send-email, request-pull, am
# - distribution: archive, submodule
FIXING PROBLEMS ==> # - removing staging area:
# - git stash: preferred, just in case change mind
# - git reset --hard
# - recovering: reflog, git fsck --unreachable, stash
┌────────────┐
│ THEORY │
└────────────┘
BRANCHING ==> #Branch goal is to put "half-done" code in separate chains:
# - isolate from each other
# - isolate from more stable code, e.g. a master can receive hotfixes without dealing with
# conflicts with current development.
GIT FLOW ==> #Types of "branches":
# - "long-living branches" with different stability level:
# - levels:
# - master: production ready (releases)
# - version TAGs should only be applied on master
# - devel: last integration state
# - merged to master for minor and major releases
# - each branch merges periodically to the one above.
# - "supporting branches" (temporary):
# - topic|feature branches:
# - branches off devel, merges back to devel
# - exist only downstream (private repos), not in public repo
# - should rebase frequently to get upstream changes
# - next|release-VERSION branches:
# - branches off devel, merges back to master and devel
# - exist in public repo
# - when next release is ready feature-wise in devel, do the last testing|QA on this
# temp branch (beta, rc, etc.)
# - chooses VERSION number and whether it is minor|major at that stage
# - hotfix/maintenance-* branches:
# - branches off master
# - merges to master and devel
# - if next exists: master and next instead. devel can then merge from next if urgent
# - bumps bugfix number
# - support-* branches:
# - when need to apply bugfix, but not to latest version of master
# - branches off master, from past commit.
# - apply fixes directly on the support-* branch
# - cannot merge back, just delete when not supported anymore
# - if decide to apply hotfix to newer commits though, can merge it to hotfix branch
#Small topic branches:
# - often integrated into devel branch
# - devel branch runs CI software to make sure it doesn't break other people changes
# - don't do back-merge: pulling from devel on a topic branch, often to get some features done
# by others (means topic branches not independant|small enough). If still done, use
# cherry-pick
#Use pull --rebase, rebase temp branches before merging
git flow #Bash script (0.4.2-pre)
git flow init [-d] #Does (interactively unless -d):
# - if no .git/, git init and create master|develop branches
# - (required for other commands to work), git config gitflow OBJ:
# - branch.master|develop (def: "master|develop")
# - prefix.feature|release|hotfix|support|versiontag
# (def: "feature/|release/|hotfix/|support/|")
#Below: f means feature, r release, h hotfix, s support
git flow f|r|h|s #List branches
git flow f|r|h|s start
NAME [COMMIT] #Create branch: git checkout -b
git flow f|r|h finish NAME #Merges back branch: git merge --[no-]ff
git flow f publish NAME #Push to origin: git fetch origin, git push origin
git flow f pull REMOTE NAME #Pull from origin: git pull
GITHUB FLOW ==> #Everyone has a fork of the origin.
#Instead of merging to master|develop locally, send a pull request to origin.
OTHER MODELS ==> #Other smaller model:
# - only a master branch with topic|hotfixes branches
# - simpler for smaller projects, but harder to stabilize release candidates (no next branch)
POSSIBLE SETUPS ==> #Centralized: each developer push/pull from one Git server
# - There can be different level of write access, e.g. few can write on master branch, but
# anyone can create topic branches
#Integration manager:
# - There is one official Git server, managed by one maintainer.
# - Developers have their own Git server. They fork the official Git server, i.e.:
# - Maintain a LRBRANCH to upstream project to pull updates.
# - Use specific LBRANCH instead of using/merging to/pushing master branch.
# Master branch will only be used as a reference to LRBRANCH, and LBRANCH the forked
# modifications will be pushed.
# - Send pull requests upstream when work is done (often a specific feature).
# Can use git request-pull.
# Maintainer will pull the fork if agreed.
# - Some other projects prefer to get patches by email.
# - Advantage: level of control, while still allowing developers to work at their own pace and
# have write access without maintainer controlling access control/adding new users.
# - If several developers need to work on one branch, can create it and ask them to send pull
# requests.
#Dictator/Lieutenant:
# - Same but there are several degrees of maintainer.
# - First-level maintainers are "lieutenants", and they send pull requests themselves to the
# "dictator benevolent" who manage the official repository.
BEST PRACTICES ==> # - Do backups
# - Don't modify history of already pushed commits or if there are downstream branches:
# rebase, commit --amend, filter-branch
# - It would force everyone downstream to rebase, otherwise a normal merge will create
# duplicate commits
# - For the first two, post-rewrite HOOK is fired
# - Don't retag already pushed tags
# - Divide modules into different repositories
COMMIT BEST PRACTICES ==> #Comment:
# - Should explicit what's been done.
# - Good style:
# - short one-liner (50 chars) summary followed by blank line then paragraphes of changes
# (present tense, contrast with previous behavior).
# - Should put blank lines between paragraphes, and between bullet points (that start with
# space then dash then space), with 72 chars wrapping.
# - Use imperative instead of past|present
# - Show why it should have changed and how it did
#Commits:
# - Put related changes in separate commits, for easier diff/recovery/managing.
# If several features at once, separate them, including using git add --patch
# - Do small commits, possibly squashing them locally later
#Do not commit:
# - anything that can be regenerated from source (compilation, autodoc, archives, etc.)
# - local conf files
# - big files
# - OS-specific files
# - log files
┌────────────────┐
│ REPOSITORY │
└────────────────┘
git init [DIR] #Create a repository at ENVVAR GITDIR (def: DIR/.git/) (def DIR: $PWD)
#After creating .git/config, empty .git/objects|refs, .git/HEAD, also copy files from
#TEMPLATEDIR/*:
# - includes .git/hooks and .git/info/exclude
# - where:
# - by def. /usr/share/git-core/templates/
# - can be overriden with CONFVAR init.templatedir, ENVVAR GIT_TEMPLATE_DIR or --template DIR
# - can run git init again later to update files from TEMPLATEDIR
--bare #Creates bare repository in $PWD.
--separate-git-dir=DIR2 #Instead of creating in GITDIR, create in DIR, then use symlink (actually a regular file) from
#GITDIR to DIR2. Can be done on an existing repository to move GITDIR to DIR2.
#Goal: put .git/ on a separate place.
-q #Quiet
--shared=PERM|WORD #Umask:
# - by def. files in .git/ are created with permissions:
# - 0777: directories, .git/hooks
# - 0444: .git/objects
# - 0666: all other files
# - always apply current umask too
#Pushes are controlled by CONFVAR core.sharedRepository PERM:
# - umask|false: none, meaning same as umask
# - 06XX permissions (X cannot include execution)
# - group|true: 1, i.e. 0660 + umask
# - all|world|everybody: 2, i.e. 0664 + umask
#Setting PERM sets CONFVAR receive.denyNonFastForwards true
.git/ #Folder holding a repository, i.e. database of all files in $PWD (called WORK_PWD), with also
#their former versions and some metadata (commits and tags).
#Stored at .git/objects/:
# - Key-value store where HASH_ID is stored as DIR/FILE (DIR is first 2 chars, FILE other chars)
# - Value is header "TYPE SIZE\0" + content, compressed with zlib:deflate
# - Content depends on type:
# - "commit" (commit):
# - link to a specific version of WORK_PWD, as a "tree", with metadata (message), and link
# to previous version, as a parent "commit" (none if initial commit), and other
# parent "commit" (if merge)
# - content: "tree", parent "commit", commit message
# - "tree" (directory): HASH_ID and filenames of "blobs" and/or "trees"
# - "blob" (regular file): file content (not filename)
# - "tag" (annoted tag):
# - like an unmovable LBRANCH, with metadata (tag name and content)
# - content: pointed "commit", tag name, tag content
#HASH_ID:
# - SHA1(Header + content)
# - COMMIT is "commit" HASH_ID. Can also be:
# - only first characters as long as there are no ambiguity and there are at least 4 chars.
# - BRANCH: cf branches
# - COMMIT_RANGE: several COMMIT:
# - COMMIT [[^]COMMIT2...]: all commits before COMMIT:
# - COMMIT2: or before COMMIT2
# - ^COMMIT2 or --not COMMIT2: but not before COMMIT2 (included)
# - [COMMIT]..[COMMIT2]: like COMMIT2 ^COMMIT (def COMMIT2: HEAD)
# - [COMMIT]...[COMMIT2]:
# - like COMMIT..COMMIT2 or COMMIT2..COMMIT
# - in other terms, be COMMIT3 closest ancestry, COMMIT COMMIT2 ^COMMIT3
# - COMMIT^@: all commits before COMMIT, except COMMIT
# - COMMIT^!: only COMMIT
# - COMMIT^{tree}: HASH_ID2 of COMMIT main "tree"
git hash-object -- FILE #Returns HASH_ID of FILE
-t TYPE #TYPE of FILE. If not "glob" (def), must respect uncompressed structure of "tree", "commit" or
#"tag"
-w #Stores in .git/
--stdin #Instead of FILE
#Should specify --path FILE to signify original path.
--stdin-paths #Use <FILE, where FILE is list of paths
git cat-file HASH_ID #Do any of following action to object with HASH_ID:
# -p: show uncompressed content (prefer git show)
# -t: show type
# -s: show size
# -e: exit with code 0 if object exists
--batch #Use <FILE with list of HASH_ID instead
--batch-check=FORMAT #Same but can use format string
git-repack #Create packs:
# - compact database used instead of .git/objects/DIR/FILE:
# - stores using deltas instead of using the whole files
# - can also create packs of packs, tags and branches
# - locations:
# - .git/objects/info/packs: list of PACKID.pack
# - .git/objects/pack/pack-PACKID.idx|pack
# - .git/packed-refs for .git/refs/
git-pack-objects #Similar
git verify-pack PACKFILE.idx #Show pack content and deltas
-v #Verbose
-s #Show stats
git prune-packed #Remove objects already in a pack
git gc #Do maintainance tasks:
# - If CONFVAR gc.packrefs notbare|true (def), create packs:
# - removes old orphan objects, with --prune=all|DATE (def: --prune=CONFVAR gc.pruneExpire)
# (def: 2 weeks)
# - cleans reflog (see above)
# - CONFVAR gc.rerere[un]resolved: clean conflicted merges records (def: 15 days and 60 days)
--auto #Only perform if:
# - more than CONFVAR gc.auto NUM objects (def: 7000)
# - or more than CONFVAR gc.autopacklimit NUM packs (def: 50)
#Automatically done by some operations.
#Runs pre-auto-gc HOOK
--aggressive #Takes longer but more efficient. Time depends on CONFVAR gc.aggressiveWindow (def: 250)
--quiet #
┌──────────────┐
│ BRANCHES │
└──────────────┘
LBRANCH #Reference to a COMMIT (usually the last of a "branch"), that can be used as such.
#Is at .git/refs/LBRANCH, whose content is COMMIT
HEAD #Reference to current LBRANCH, that can be used as such.
#Is at .git/HEAD, pointing to .git/refs/heads/LBRANCH
.git/logs/HEAD #"reflog", i.e. local temp history of HEAD content (across any LBRANCH switch)
#As opposed to git log, includes going back and forth in the history and switching LBRANCH.
#Can undo git reset COMMIT, by creating a LRBRANCH pointing to previous HEAD
#Enabled by CONFVAR core.logAllRefUpdates (true for non-bare repository, false otherwise).
#To enable on specific branches when false, use git branch|checkout -l when creating it.
.git/logs/refs/heads/LBRANCH #Same for specific LBRANCH's HEAD
[LBRANCH]@{NUM|DATE} #NUMth last position in .git/logs/refs/heads/LBRANCH reflog (def: HEAD)
#DATE can be: YYYY-MM-DD[ HH:MM[:SS]], NUM month|weeks|days|hour|second ... ago or yesterday
git log -g ... #Show reflog. Can also use --grep-reflog=REGEXP
git reglog ... #Same as git log -g --abbrev-commit --pretty=oneline ...
git reglog delete ...@{...} #Erases reflog entry (but not commit)
git reflog expire #
[HEAD|LBRANCH] #Erases reflog old reflog entries. Done automatically by gc
--expire[-unreachable]=TIME #Time limit for [un]reachable commits to be considered old.
#Def.: CONFVAR gc.reflogExpire[Unreachable], which def. to 90|30 days
--all #All HEAD|LBRANCH
--rewrite #Rewrite reflog after erasing items.
ORIG_HEAD #Reference to last HEAD when using commands that change HEAD drastically, e.g. checkout or reset
COMMIT^[2] #Parent COMMIT2. Use ^2 to differentiate if there are two parent COMMIT (merges)
COMMIT^[2]^[2]... #Grand parent COMMIT3, and etc.
COMMIT~NUM #Same as COMMIT^ with NUM ^
#Can be combined, e.g. COMMIT^2~3^2
:/REGEXP #Matches closest COMMIT with commit message matching REGEXP, reachable from any LBRANCH
COMMIT^{/REGEXP} #Same but from COMMIT
COMMIT:FILE #Version of file at COMMIT (e.g. with git show)
"BRANCH" ==> #LBRANCH and all parent COMMITs
#Called "branch" in this doc, as opposed to LBRANCH, LRBRANCH, RBRANCH, BRANCH
#Forks are several "branches" with common COMMIT ancestor.
git branch --list [GLOB...] #Show all LBRANCH matching any of GLOB
-r #Show LRBRANCH instead
-a #Show LRBRANCH and LBRANCH
-v #Show last commit too
-vv #Show tracked LRBRANCH too
-q #Quiet
--contains [COMMIT] #Only show branches that contains COMMIT (def: HEAD)
#Useful when rebasing COMMIT.
--[no-]merged [COMMIT] #Only show branches that are [not] completely included before COMMIT (def: HEAD)
#--merged is useful to check which branches are useless and can be deleted
#--no-merged is useful to check which branches can be merged.
git branch --edit-description #Creates a message describing the branch (used by request-pull and some editors)
[LBRANCH] #Can also use CONFVAR branch.LBRANCH.description
git branch LBRANCH [COMMIT] #Create a LBRANCH that points to COMMIT (def: HEAD).
#If COMMIT is LRBRANCH, tracks it:
# - Can [not] force with --[no-]track
# - Can setup later with git branch -u LRBRANCH, or unset with git branch --unset-upstream
-f #Modifies existing branch instead
git branch -m|M LBRNCH LBRNCH2#Rename branch (-M to force even if LBRANCH2 exists)
git branch -d|D LBRANCH #Deletes branch (-D to force event if not merged in upstream branch, or in HEAD if no upstream)
-r #Use for LRBRANCH
git checkout [COMMIT] #Switches HEAD to COMMIT. Special cases:
[-- FILE|DIR] # - if COMMIT is HEAD (def), does not do anything
# - if COMMIT is not a LBRANCH, is in "detached HEAD" mode:
# - When HEAD does not point to a LBRANCH, but to a normal COMMIT.
# - It needs to be attached to a LBRANCH by creating it.
# - if COMMIT is LBRANCH but --detach is used, use "detached HEAD" mode
# (commits won't update LBRANCH)
#Keeps staging area modifications:
# - if adding|removing files, no conflicts
# - if modifying files, conflicts:
# - if -m, enters conflict mode
# - can use --conflict="merge|diff3" instead to set CONFVAR merge.conflictstyle
# - if -f, discards staging area
# - if -f --ours|theirs: keeps only COMMIT|COMMIT2 state
# - otherwise, error
# - it is better not to have staging area: commit + commit --amend, or stashing
#Can use [LBRANCH]...[LBRANCH2] to signify common COMMIT ancestor (def each: HEAD)
#Fires HOOK post-checkout (e.g. setting up environment)
-q #Quiet
--orphan LBRANCH #Creates a new LBRANCH starting at COMMIT, whose first COMMIT2 will be the starting point of
#a LBRANCH disconnected to other branches. To make sure it really is disconnected, use
#git rm -rf ., then copy manually the files and re-git add tem.
#Goal is to publish an open source LBRANCH without publishing proprietary code in history.
git checkout -b|B LBRANCH
[--[no-]track] [COMMIT] #Same as git branch [-f] [--[no-]track] LBRANCH [COMMIT]; git checkout LBRANCH
git checkout [COMMIT|TREE] #Modifies FILE|DIR in the same state as in COMMIT|TREE, and (if not HEAD) stages it.
-- FILE|DIR #Ignore files matching pattern files .git/info/sparse-checkout unless --ignore-skip-worktree-bits
-p #Produces and apply a patch instead, in order to only apply partial modifications.
CONFATTR filter=FILTER #With CONFVAR filter.FILTER.smudge|clean PROGRAM, where PROGRAM STR -> STR2:
# - clean applied at checkout
# - already available: ident, which replaces "$Id$" by "$Id: FILE_SHA1 $"
# - smudge applied before commit
git reset [COMMIT] #Switches current LBRANCH (including HEAD) and:
# --soft: keep WORK_PWD and list of tracked files
# --mixed (def): same but also unstage staging area
# --hard: don't keep WORK_PWD and list of tracked files, and discard staging area
# --keep: same but keep files in WORK_PWD not present in COMMIT.
# Aborts if some files are different between both.
# --merge: same but only aborts if differences are unstaged
#With no COMMIT, will just unstage everything (--mixed) or discard staging area (--hard)
#git branch LBRANCH + git reset COMMIT -> separate all work between HEAD and COMMIT in a LBRANCH
┌──────────┐
│ TAGS │
└──────────┘
TAG ==> #Unmovable LBRANCH (can be used as such), pointing to a COMMIT.
#If "annoted", also has metadata: signature, content.
#Stored at .git/refs/tags/TAG:
# - normal tag: "commit" HASH_ID
# - meant for private/temp commit tabel
# - annoted tag (tag -a): "tag" HASH_ID
# - Less frequent than commits, meant for specify/sign release versions, on commits changing
# only release notes-related files.
#Fetched automatically, but not pushed: must git push REPO TAG|--tags
TAG^{commit} #Only designates the COMMIT underlying the TAG (usually automatically done)
git tag STR [COMMIT] #Creates a tag pointing to COMMIT (def: HEAD).
-a #Create an annotated tag
-s #Uses CONFVAR pgp.program and CONFVAR user.signingkey (def: user.name <user.email>)
-u KEY #Same with explicit KEY
-m STR
-F FILE #Stores a comment (annotated tag)
-f #Creates even if already existing
git tag -d STR #Deletes a tag
git tag #Show all tags
-l GLOB #Show tags that match GLOB
-n [NUM] #Only prints first NUM lines of message (def: 1)
--contain [COMMIT] #Only prints tags that are at or after COMMIT (def: HEAD)
--points-at [COMMIT] #Same for only at COMMIT
--cleanup=MODE #Modifies message:
# - verbatim: does not modify
# - whitespace: removes leading|trailing whitespaces
# - strip (def): also removes comments
git tag -v TAG #Verify a TAG, using a GPG public key (must be configured)
git describe [COMMIT] #Prints closest annotated TAG as TAG[-NUMBER_COMMITS_AWAY-gTAG_COMMIT]
--tags #Also matches non-annotated TAG
--all #Also matches LBRANCH (as heads/LBRANCH)
--dirty[=STR] #Appends STR (def: "-dirty") if [un]staged modifications.
--contains #Look forward, not backward
--match GLOB #Only tags that match GLOB
--first-parent #When forks, only take first parent (master)
--candidates=NUM #Take max. NUM forks (def: 10, 0 for unlim)
┌──────────────────┐
│ STAGING AREA │
└──────────────────┘
.git/index #Staging area: current modifications that will be saved by next commit.
#Goal is to give flexibility in what to commit.
#Commit:
# - saves and clears staging area
# - points to current state with COMMIT
# - doesn't include unstaged modified files, which stays as is
#"Untracked" files are unstaged files that have never been committed in the past.
#Stage file modifications, not files, so need to restage if new modification on same file.
GITIGNORE ==> #File at:
# - ~/.config/git/ignore
# - .git/info/exclude
# - [../[../]]./.gitignore
# - CONFVAR core.excludesfile
#Specify files that cannot be staged and are not shown as untracked.
#Each line is a globbing pattern (include globstar):
# - !GLOB: include previously excluded pattern
# - if no slash, matches filename not path
# - Can have #comment
git status #Show current staged area, modified unstaged area, untracked files, conflicted merged files.
#If CONFVAR status.relativePaths false, show paths relative to project root, not $PWD
-s #Short output
-b #Show current branch with -s
--untracked-files=WORD #How untracked files are shown:
# - no: not shown
# - normal (def): regular files and directories, not recursively
# - all: regular files only, recursively
#Can also use CONFVAR status.showUntrackedFiles
--ignored #Show files ignored by .gitignore
git add FILE|DIR... #Put in staging area
-i #Interactive mode with options:
# - status: show each [un]staged file and how many lines are [un]staged
# - update|revert: stage|unstage
# - add untracked: stage untracked
# - patch: stage partial modifications ("hunks"):
# - y|n: [don't] stage this hunk
# - a|d: stage all|none
# - g|/REGEXP: go to specific hunk
# - K|J: go prev|next hunk
# - k|j: go prev|next undecided hunk
# - s: split into smaller hunk
# - e: edit hunk patch. Should undo modifs|add|removals, not add new ones.
# - q: quit (means no for all undecided hunks)
# - ?: help
# - diff: git diff
-p #Like -i followed by "patch"
-e #Like -i followed by "edit" for all hunks at once
-n #Dry-run
-f #Include files ignored by .gitignore
--[no-]all #Allow staging removals (def: yes, i.e. --all)
-u #Only stage files if already been staged for this commit
-N #Stage then unstage (so untrack)
-v #Verbose
git reset FILE|DIR... [COMMIT]#Like git checkout ... but unstages the modification.
-p #Only unstages partial modifications (use interactive prompt)
-q #Quiet
git reset [--hard] #Unstages everything or discard everything (see above)
git rm FILE|DIR #Untrack FILE and also remove FILE physically
-r #Use with DIR
--cached #Don't remove physically
-n #Dry-run
-f #Need to use if FILE|DIR has been changed since last commit
--ignore-unmatch #Exit code 0 even if no files matched
-q #Quiet
git mv FILE... FILE2 #Do cp FILE FILE2, git rm FILE, git add FILE2
#If FILE..., FILE2 has to be a DIR
#Only way to store filename changes
-f #Even if FILE2 exists
-n #Dry-run
-v #Verbose
git commit [-- FILE|DIR...] #Write staging area to current LBRANCH.
#If FILE|DIR..., use it instead of staging area (must not be untracked files), or (if -i) as well
#HOOK:
# - pre-commit: before default commit message created
# - e.g. making sure everything is ok (e.g. linting) to be committed.
# - prepare-commit-msg: after default commit message created, before editing it
# - arguments: TEMP_FILE, COMMIT_TYPE, COMMIT_SHA1
# - e.g. editing default commit message
# - commit-msg: after editing commit message
# - arguments: TEMP_FILE
# - e.g. validating commit message
# - post-commit: after committing
# - e.g. notifications
# - commit -n bypass pre-commit and commit-msg
-m STR
-F FILE #Comment. Can use - for FILE stdin.
-e #Further modify message with editor, even if -m or -F
-t FILE #Uses as default comment (def: CONFVAR commit.template)
--status #Include git status output in commit message (can use CONFVAR commit.status true)
--cleanup=MODE #Like git tag. Can use CONFVAR commit.cleanup
--author=STR #Def: CONFVAR user.name + user.email (or ENVVAR GIT_AUTHOR_EMAIL|NAME)
#If STR is not "USER <EMAIL>", is a GLOB_STR that looks for the author names in previous commits.
-s #Add "signed off by USER <EMAIL>" at end of commit message.
--date=DATE #Def: current date
--gpg-sign=KEY
-SKEY #See git tag -u KEY
-a #Automatically stage all modifications (providing files are not untracked)
--interactive
--patch #Like add -i and add -p, but for commits not staging.
-C|c COMMIT #Reuse COMMIT message, author and date. If -c, can further modify message with editor.
--reset-author #With -C|c, only reuse COMMIT message.
--amend #Replace previous commit, instead of coming after it. Implies -c HEAD^
--allow-empty #To do when commit does not do anything (e.g. --amend that reverse previous commit)
--allow-empty-message #Same for empty message
--dry-run #Do a git status instead. Can use git status options.
-v #Verbose
-q #Quiet
git clean -- FILE|DIR... #Removes untracked files
-n #Dry-run
-i #Interactive mode
-f #Never runs unless -n or -i given, or if -f or CONFVAR clean.requireForce false
-d #Removes untracked directories too
-e GLOB #Don't remove files matching GLOB
-x|X #Also|only removes files designated by .gitignore
-q #Quiet
STASH_ITEM ==> #Reference to current [un]staging area:
# - saved in .refs/stash: list of COMMIT
# - is actually a commit with two parents (HEAD TREE, HEAD+[un]staging area TREE), but not
# treated as such
#Goal: save [un]staging area without having to commit.
stash@{NUM|DATE} #STASH_ITEM (0 for most recent)
git stash save [STR] #Create a STASH_ITEM of [un]staging area (not untracked files)
#STR is the STASH_ITEM message (def: "WIP on LBRANCH: COMMIT COMMIT_MESSAGE")
#Should use descriptive STR instead of default.
--[no-]keep-index #[Don't] run reset --hard
--include-untracked #Include untracked files, then run git clean .
--all #Same as --include-untracked but also include then clean files ignored by .gitignore
-p #Interactive mode, to only include partial modifications. Implies --keep-index
git stash apply|pop
[STASH_ITEM] #Apply STASH_ITEM (then git stash drop) (def: stash@{0})
--index #Also reapply which files were staged or not
-q #Quiet
git stash list [...] #List all STASH_ITEM. Same options as git log
git stash show [STASH_ITEM] #Show STASH_ITEM. Same options as git diff (e.g. -p to show as patch)
git stash drop [STASH_ITEM] #Remove from stash list
-q #Quiet
git stash clean #Remove all STASH_ITEM
git stash branch LBRANCH #Creates LBRANCH with stash content.
[STASH_ITEM] #I.e. do git branch LBRANCH, git checkout STASH_ITEM last COMMIT, git pop STASH_ITEM
git revert COMMIT[_RANGE]... #Do a commit that reverts COMMIT...
#Alternative to git commit --amend, git rebase or git reset
#If merge conflict: like git cherry-pick (including --continue|abort)
-n #Only stage the modification, but don't commit them
-mNUM #When COMMIT is a merge commit, choose to undo the merging branch (1) or the other (2)
-s #Like git commit
--strategy=STRATEGY
-X STRATEGY_OPT #Used for merge conflicts (see git merge)
┌────────────┐
│ SERVER │
└────────────┘
GIT SERVER ==> #REPO used to share work of several developers.
#DIR is often called PROJECT.git/
#Since only cloned but not manipulated, should be a "bare REPO":
# - only the .git/
# - allow getting pushed
# - CONFVAR core.bare true
# - created by clone|init --bare
#Mirror repository: Git server that duplicates another, to provide backups, or scale performance.
REMOTE REPOSITORY ==> #.git/ that can be accessed|written from outside.
#Can use protocols:
# - Local (file:///PATH.git, implies --local with git clone)
# or /PATH.git (does not imply --local with git clone)):
# - when using NFS or using same computer
# - SSH (ssh://USER@SERVER/PATH.git or USER@SERVER:PATH.git):
# - only that can write.
# - But to allow read without requesting client to setup SSH, use Git/HTTP for read.
# - Access control:
# - Good idea to have only one "git" user account with shell /usr/bin/git-shell in
# /etc/passwd (restricted shell), and ask public keys of people who want to push.
# - Gitolite permits different access control (otherwise every SSH user has full
# read+write access to everything), which can be turned on by branches.
# - Git (git://PATH.git): faster, but harder to setup (better than HTTP then).
# - HTTP (http://PATH.git): slower, but easier to setup: enable HOOK post-update from
# .git/hooks/post-update.sample
USING OWN SERVERS (NOT GITHUB)
==> #See chapter 4 (Git on the server) and 9.6 (Transfer protocols) of Git online doc
┌───────────────────────┐
│ REMOTE OPERATIONS │
└───────────────────────┘
REPO #Reference to a remote repository, containing default URLs and branches for git push|fetch.
RBRANCH #REPO remote LBRANCH (not accessible directly)
LRBRANCH #Local reference to RBRANCH, written [remotes/]REPO[/LRBRANCH].
#LRBRANCH def. is HEAD, but only stored if git remote set-head
#Objects are stored locally like an LBRANCH, and reference to LRBRANCH are in
#.git/refs/remotes/REPO/LRBRANCH. However should try to use it only with fetch|merge|push|pull.
TRACKING BRANCH ==> #CONFVAR branch.LBRANCH.remote REPO and CONFVAR branch.LBRANCH.merge refs/heads/RBRANCH:
# - gives default LRBRANCH for git pull|rebase|merge
# - shown in git branch -vv and git status
# - can be disabled with CONFVAR branch.autosetupmerge false
#Upstream branch is another name for tracked branch.
LBRANCH@{u} #Same as LRBRANCH tracked by LBRANCH
git remote #Show all REPO
-v #Prints URL too
git remote show REPO #Show info about REPO: fetch URL, push URL, HEAD branch, RBRANCH, push refspec
-n #Less info but does not require internet connection
git remote add REPO URL #Adds remote.REPO.url|fetch
-f [--[no-]tags] #Runs git fetch [--[no-]tags] immediately
-t RBRANCH #Only track RBRANCH (can be specify multiple times) by modifying refspec
-m RBRANCH #Does git remote set-head REPO RBRANCH too
--mirror=fetch #Uses remote.REPO.fetch +refs/*:refs/*, meaning git fetch will create LBRANCH not LRBRANCH
#To use with bare mirror repositories
--mirror=push #Uses remote.REPO.mirror true, and no remote.REPO.fetch
git remote rename REPO REPO2 #
git remote update [NAME] #Do git fetch NAME. If no NAME, all REPO, except ones with CONFVAR
#remote.NAME.skipDefaultUpdate true
--prune #See git remote prune
-v #Verbose
git remote rm REPO #
git remote prune REPO #Removes stale LRBRANCH, i.e. pointing to non-existing RBRANCH in REPO
--dry-run #
git remote set-url [--add]
[--push] REPO URL #Adds|replaces remote.REPO.[push]url
git remote set-branches
[--add] REPO RBRANCH... #Adds|replaces remote.REPO.fetch (like using git remote -t RBRANCH ...)
git remote set-head
REPO RBRANCH #Sets REPO's HEAD (to use as default LRBRANCH for REPO).
-d #Deletes REPO's HEAD
-a #Determines RBRANCH by looking at REPO actual HEAD
git fetch [NAME] [REFSPEC...] #Copy RBRANCH to LRBRANCH
#Def REFSPEC: use "refspec" (see above).
#For a given remote repository at URL[s] NAME:
# - REPO_URL
# - REPO: uses CONFVAR remote.REPO.url
# - CONFVAR remotes.NAME REPO...
# - CONFVAR remotes.default REPO...
# - if --all, all remotes.REPO
# - current LBRANCH's upstream LRBRANCH REPO
# - Can be NAME... if --multiple
#For CONFVAR remote.REPO.fetch [+]RBRANCH:LRBRANCH ... ("refspec"):
# - copies REPO's RBRANCH:
# - creates|updates LRBRANCH
# - copies all objects and commits up to RBRANCH
# - copies tags up to RBRANCH, unless using --[no]-tags or CONFVAR remote.REPO.tagopt
# - usually +refs/heads/*:refs/remotes/REPO/*
# - can use remote.REPO.fetch = ... several times for several branches
# - can use globbing *
# - can create directory in LRBRANCH to make namespaces
# - + allows non-fast-forward fetches
# - [L]RBRANCH can be TAG since it can always be used as a branch
#No REFSPEC if --multiple of NAME not REPO
--prune #See git remove prune
--progress #Progress bar
--dry-run #
-q #Quiet
-v #Verbose
git pull [REPO] [RBRANCH] #git fetch REPO RBRANCH + git merge|rebase FETCH_HEAD HEAD (according to --rebase)
#To cancel conflicting merge, do git reset --merge
#Uses same options as git merge|rebase|fetch (in that order)
#Def. REPO is "origin" or branch.LBRANCH.remote|merge if there is an upstream branch
-q #
-v #
git push REPO [REFSPEC] #Copy LBRANCH to RBRANCH (inverse of git pull)
#REPO:
# - REPO_URL
# - CONFVAR remote.REPO.[push]url
# - "origin"
#REFSPEC: [+]COMMIT:RBRANCH
# - COMMIT is usually a LBRANCH
# - e.g. refs/heads/*:refs/heads/*
# - RBRANCH can contain directories, to create namespaces
# - if no REFSPEC or no :RBRANCH:
# - uses CONFVAR remote.REPO.push
# - uses CONFVAR push.default:
# - "nothing": emits error
# - "current": use HEAD as source, RBRANCH with same name as dest
# - "upstream": use HEAD as source, HEAD@{u}'s RBRANCH as dest
# - "simple" (def): same but error if RBRANCH name is different that HEAD
# - "matching": push all branches with same names.
# - if no COMMIT, erases RBRANCH
# - if no COMMIT and no RBRANCH (e.g. ":"), uses matching LRBRANCH <-> RBRANCH
# - if --all, refs/heads/*:refs/heads/*
#TAG are only pushed if --tags (all TAG) or --follow-tags (annoted TAGs at|before COMMIT)
#Fires HOOK:
# - pre-push, unless --no-verify
# - on REPO:
# - pre-receive:
# - receives data from stdin
# - update:
# - same but with different arguments and fired once by pushed branch if several branches
# pushed
# - post-receive:
# - receives data from stdin
# - e.g. notifications
#Only if REPO is bare server.
#When receiving pushes can set up CONFVAR:
# - receive.denyNonFastForwards true
# - receive.denyDeletes true: denies remote branch erasing
--mirror #Push refs/*:refs/*, so it includes TAG and LRBRANCH
#Can also use CONFVAR remote.REPO.mirror true
--prune #Removes RBRANCH if no matching LBRANCH
--dry-run #
-u #Make every LBRANCH track RBRANCH
--progress #Progress bar
-q #Quiet
-v #Verbose
git clone REPO_URL [DIR] #Copy repository from REPO_URL to ./DIR
#Actually do:
# - git init [DIR]
# - git remote add "origin" REPO_URL, with refspec +refs/heads/*:refs/remotes/REPO/*
# - can use -o NAME instead of "origin"
# - git fetch
# - make each LBRANCH track LRBRANCH (unless --bare)
# - git checkout HEAD (unless -n)
--local #When using file protocol, hardlink.
--bare #Copy only .git/
--mirror #Like --bare, plus:
# - CONFVAR origin.mirror true
# - CONFVAR origin.fetch +refs/*:refs/*
--depth NUM #Only copy up to HEAD~NUM ("shallow repository").
#Can then deepen|shorten with git fetch --depth=NUM, or git fetch --unshallow
#.git/shallow:
# - keeps depth (COMMIT list)
# - if git fetch tries to modify this file, aborts unless git fetch --update-shallow
--[no-]single-branch #Only copy the designated branch (def if --depth)
--template=DIR #Like git --init
--separate-git-dir=DIR #Like git --init
--progress #Progress bar
-q #Quiet
-v #Verbose
┌─────────────┐
│ PATCHES │
└─────────────┘
git diff [COMMIT] [COMMIT2] #Show diff (patch) from COMMIT to COMMIT2:
[-- FILE|DIR...] # - If no COMMIT2: WORK_PWD (not untracked files)
# - if --cached, only staging area, if not, only not staging area
# - If no COMMIT: HEAD
#If FILE|DIR, only diff those ones.
#Can also use:
# - COMMIT...COMMIT2 meaning COMMIT common_ancestor(COMMIT,COMMIT2)
# - BLOB_ID BLOB2_ID
# - FILE FILE2, if --no-index
-UNUM #Patch context lines (def: 2)
-W #Context lines are current functions
--diff-algorithm=WORD #Can produce smaller|differently chunked patches.
#Is myers (def), minimal, patience or histogram, of CONFVAR diff.algorithm
--word-diff #Instead of line diff
#What is a "word" can be specified with --word-diff-regex=REGEXP
--diff-filter=CHAR... #Only show diffs that matches CHAR: A (added), D (deleted), M (modified), R (renamed), C (copied)
#T (type changed), U (unmerged), X (unknown), B (pairing broken)
-M[NUM%] #Detect renames not done with git mv (if more than NUM% similar)
-C[NUM%] #Same for copies + renames
-GREGEXP #Only show diffs that contained modified lines matching REGEXP
-SSTR #Only show diffs that changed number of occurences of STR in the file
#If --pickaxe-regex, can use REGEXP instead of STR
--pickaxe-all #Show diff in files, not only files themselves with -G or -S
--relative[=DIR] #Only show diffs in DIR (def: $PWD)
-R #Swaps COMMIT and COMMIT2
-OFILE #Specify files order in patch. FILE has one pattern per line. Can use CONFVAR diff.orderfile
-p #Generates patch even when --*stat is used
--stat #Generates summary instead
--numstat #Similar but less pretty
--shorstat #Similar but more concise
--dirstat #Similar but showing percentage by directory
--summary #Another one
--name-only|status #Only show modified files filenames [with the type of modification]
--check #Show whitespaces errors, i.e. changes only due to whitespaces, e.g. trailing whitespaces, etc.
#Good idea to check them before committing.
BINARY DIFF ==> #git diff on binary files:
# - just says if differs or not
# - CONFATTR diff=DIFFFILTER to convert binary to text, or diff --textconv=PROGRAM
# - must CONFVAR diff.DIFFFILTER.textconv PROGRAM, where PROGRAM STR -> STR2
# - ex. of PROGRAM: catdoc for *.doc, odt-to-txt for *.odt, exif-tool for *.png metadata
# - CONFATTR -diff: forces binary diff (otherwise guessed automatically for binary files)
#CONFATTR binary: same as -crlf -diff
#Can also use git diff --binary, which can be applied with git apply
WHITESPACES ==> # - checked by git diff --check or git apply|rebase --whitespace=warn|fix
# - CONFVAR core.whitespace VAL,...:
# - trailing-space (def)
# - space-before-tab (def)
# - indent-with-non-tab: lines that start with 8 or more spaces
# - cr-at-eol: CRLF are ok
# - not done if binary file. Guessed automatically, but can force with CONFATTR -crlf
# - git diff:
# -b|w: ignore whitespaces changes [even when line without whitespaces -> whitespaces]
# -ignore-blank-lines
# - git apply:
# --ignore-space-change, or CONFVAR apply.ignorewhitespace change
# --whitespace=ACTION, when whitespace errors (according to CONFVAR core.whitespace):
# nowarn, warn (def), fix, error, or CONFVAR apply.whitespace
git apply FILE... #Apply a patch FILE (output of git diff) to:
# - WORK_PWD
# - --index: WORK_PWD + staging area
# - --cached: only staging area
#Conflict:
# - if:
# - adding already existing files
# - modifying|removing removed files
# - reject whole patch, or if --reject, leaves rejected hunks in *.rej
-R #Applies in reverse
-CNUM #Number of context lines
--stat|numstat|summary|check #Show same output as git diff ... If --apply, also do the patch apply.
-3 #3 way merges
--exclude|include=GLOB #Only applies to those files
-v #Verbose
-p[NUM] #Removes leading slashes (def: 1)
--directory=DIR #Appends DIR to filenames
┌────────────┐
│ EMAILS │
└────────────┘
git format-patch #Creates patches to send by email
git send-email #Send patches by email
git request-pull #Ask for upstream to pull by email, sending patches
git am #Apply patches received by email
#HOOKS:
# - applypatch-msg: after editing commit message.
# - arguments: TEMP_FILE
# - pre-applypatch: after patch applied, before commit
# - post-applypatch: after patch applied, after commit
┌──────────────────────┐
│ MERGING BRANCHES │
└──────────────────────┘
CONFLICTS ==> #With merging, rebasing, patching, applying staging area to another COMMIT, pushing/pulling:
# - Always tries to automerge: modification is applied to files, creation/removals are done.
# - Doesn't ask for confirmation, including for push/pull.
# - However, not done if two conflicting modifications (including creation/removal) on same file
# - Abort current operation and ask to solve it (doesn't automatically do it)
# - Handling conflicts:
# - Can see with git status
# - Enters conflict mode
#Conflict mode:
# - Add headers around differences in conflicting files (need to remove them)
# - Can use git mergetool to run PROGRAM (e.g. vimdiff) to put modified conflicting files
# in non-conflicting state.
# Uses CONFVAR merge.tool: used when conflicts (e.g. "vimdiff")
# Will create FILE.orig for backup. Needs to commit modification resolution.
# - Can git merge --abort
# - MERGE_HEAD: points to COMMIT2
# - :NUM:PATH: refers to file PATH version at: 1 (common ancestor), 2 (COMMIT2), 3 for COMMIT
# - git log --merge -p FILE|DIR... show change introduced by COMMIT2, then by COMMIT
git merge [COMMIT] [COMMIT2] #Creates COMMIT3 -> COMMIT2 + patch(COMMIT) (def COMMIT2: HEAD)
#Default COMMIT is FETCH_HEAD, i.e. LBRANCH with last git fetch, or if
#CONFVAR merge.defaultToUpstream true, COMMIT2@{u}
#Can set up default options for merging into LBRANCH with CONFVAR branch.LBRANCH.mergeoptions
#If COMMIT is LBRANCH, should then erase merged branch.
#Fires HOOK post-merge (e.g. restoring file permissions)
--ff #If fast-forward, do not commit: only update HEAD (def unless COMMIT is TAG)
--no-ff #Inverse (def if COMMIT is TAG): will keep merge info even if fast-forward
--ff-only #Aborts if not fast-forward. Can use CONFVAR merge.ff true|false|only
--no-commit #Stage modifications but do not commit
--stat #Show a diff --stat at end of commit message. Can use CONFVAR merge.stat
--log[=NUM] #Put merged branch commits titles in commit message (truncate at max NUM lines)
#Can use CONFVAR merge.log
-m STR
-SKEY #Like git commit
--verify-signatures #Verify commits GPG signatures
--progress #
-q #
-v #Can use CONFVAR merge.verbosity 0-5
--squash #Performs a fast-forward merge, but erase forward history (keep current HEAD).
#Useful to merge several commits into one.
-s STRATEGY #What to do when merge conflict:
# - "recursive" (def): WORK_PWD gets non-conflicted modifications, and others are asked for a
# 3-way merge. STRATEGY_OPT:
# - "ours|theirs": automatically privilegy COMMIT2|COMMIT version
# - "ignore-space-change", "ignore-all-space", "ignore-space-at-eol"
# - rename-threshold=NUM: like git diff -M NUM
# - subtree=DIR: assumes COMMIT tree matches DIR, not COMMIT2 tree
# - subtree: like recurse with subtree, but guesses DIR
# - ours: drop COMMIT changes
-X STRATEGY_OPT #
git rebase [BRANCH] [BRANCH2] #Rewrite history of BRANCH2 (def: HEAD), so that it can be fast-forward merge to BRANCH
#(def: BRANCH2@{u})
#In details: checkout BRANCH2, rewrite BRANCH2 history to BRANCH (git reset --hard BRANCH),
#then apply patch(BRANCH2)
#BRANCH can be --root to mean initial COMMIT.
#If conflict, can use git rebase --continue|abort, or --skip to skip current conflicting COMMIT
#When to use rebase + fast-forward-merge instead of non-fast-forward-merge:
# - same except history (doesn't show fork, flat history):
# - avoid the mess for topic branches, but should keep merge information for longer-running
# branches, e.g. minor and major versions