-
Notifications
You must be signed in to change notification settings - Fork 0
/
git.txt
1687 lines (1214 loc) · 52.5 KB
/
git.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
# -*- mode: sh;-*-
###########
### git ###
###########
# docs:
# good learning git resources
https://learngitbranching.js.org/ - visual teaching with exercises
# tools
https://github.com/tj/git-extras/tree/master/bin
# terminology
origin = remote repository URL with short name origin
### download a sub-directory from a git tree ###
# e.g. https://github.com/buckyroberts/Source-Code-from-Tutorials/tree/master/Python
#1. replace tree/master => trunk
#2. svn co the new url
svn co https://github.com/buckyroberts/Source-Code-from-Tutorials/trunk/Python
### clone ###
# clone a private repo
git clone https://[email protected]:/stas00/fastai-transcript/
# clone a specific branch w/o fetching any other branches
git clone --single-branch --branch megatron-deepspeed https://huggingface.co/bigscience/gpt2-350m-en
# clone a specific branch after fetching all branches
git clone --branch megatron-deepspeed https://huggingface.co/bigscience/gpt2-350m-en
### add ###
git add [folder/file]
# undo add (before push was made)
git reset [folder/file]
### remove ###
git rm [folder/file]
# remove remote file copy only. e.g. remove database.yml that is already checked
# in but leaving the local copy untouched. This is also handy for removing
# ignored files that are already pushed without removing the local copies.
git rm --cached database.yml
# for a directory:
git rm --cached -r mydirectory
### status ###
git status
# brief status
git status -s
# brief status excluding untracked files
git status -s -uno
# get the status of the local repository compared to remote
git remote show origin
# current SHA revision
git rev-parse --short HEAD
# show only untracked files, including sub-dirs if they haven't been added yet
git ls-files --others --exclude-standard
# same but has a lot of extra noise - can't feed it into a pipe
git status -u
# show only modified files
git ls-files --modified
# current SHA / commit ID, long and short
git show -s --format=%H
git show -s --format=%h
### push ###
git push
# dry-run (do everything except for the actually sending of the data)
# but it doesn't show anything useful - see commands below for visual hints of what will happen
git push --dry-run
# show which files have changed and view the diff compared to the remote master branch HEAD
git diff --stat --patch origin master
# list of files to be pushed
git diff --stat --cached [remote/branch]
# show code diff of the files to be pushed
git diff [remote repo/branch]
# show full file paths of the files that will change
git diff --numstat [remote repo/branch]
# if the files got staged via merge, then diff against the branch itself,
git diff origin/my-branch-name
# or simpler:
git diff origin/master
# with status:
git diff --name-status origin/master
### commit ###
git commit -a
# -a is crucial as w/o it you need to 'git add' every file that has changed!
# amend (re-edit) the already committed (but not pushed file)
git commit --amend -m "Initial Commit"
# to push an empty commit - e.g. to force a CI rebuild - when there is no diff to push
git commit --allow-empty -m "Trigger CI"
git push
# commit with a different author tagged (contributor)
git commit --author "Manuel R. Ciosici <[email protected]>" -am "corrections"
### authentication ###
# cache auth
git config --global credential.helper cache
# adjust caching time
git config --global credential.helper 'cache --timeout=36000'
# can also save the password in clear if the system is safe
# this is also needed for huggingface_hub auth caching to work
git config --global credential.helper store
# to reset! e.g. when getting:
# remote: Forbidden
# fatal: unable to access 'https://huggingface.co/hf-internal-testing/tiny-layoutlm/': The requested URL returned error: 403
git config --global --unset credential.helper
### config ###
# delete/remove config entry from local repo
git config --unset user.email
# delete/remove config entry globally
git config --global --unset user.email
### update ###
git pull
# git pull is shorthand for
git fetch
git merge FETCH_HEAD
# git with sub-modules
git clone --recursive https://github.com/pytorch/pytorch
cd pytorch
#
# if you are updating an existing checkout
git submodule sync
git submodule update --init --recursive
# display the incoming/outgoing changes before pull/push
git log ^master origin/master
git log master ^origin/master
### rename multiple files
# find all files matching foo*.py and git rename s/foo/bar/ (this avoids destroying anything under .git)
# 1. rename.pl way - note that the history isn't lost if files are first deleted and then added
# `git mv` is the same as `git rm` followed by `git add`
rename.pl 's|OLD|NEW|'
git ls-files -z --deleted | xargs -0 git rm # this removes missing files as a result of rename
git add new-renamed-files
#
# 2. slightly harder way, but one command
find . -type d -name ".git" -prune -o -type f -name "foo*.py" -exec bash -c 'file={}; git mv $file ${file/foo/bar}' \;
### search/replace
# How to safely and efficiently search/replace files in a git repo using CLI
# must not touch anything under .git/
find . -type d -name ".git" -prune -o -type f -exec perl -pi -e 's|OLDSTR|NEWSTR|g' {} \;
# but it touch(1)es all files which slows down git-side
# so we want to do it on files that actually contain the old pattern
grep --exclude-dir=.git -lIr "OLDSTR" . | xargs -n1 perl -pi -e 's|OLDSTR|NEWSTR|g'
# a more efficient version as it only looks inside git files
# after adding to your ~/.bashrc and starting a new bash shell
# usage: git-replace oldstr newstr
#
function git-replace () {
files=$(git grep -l "$1")
if [[ ! -z "$files" ]];
then
perl -pi -e "s|$1|$2|g" $files
git diff --shortstat
else
echo "no match for: $1"
false
fi
}
### git GUI ###
# git
git gui
# gitk
gitk --all
### contributors ###
# show a list of contributors ordered by number of commits. Similar to the contributors view of GitHub.
git shortlog -sn
### status and information
# short form log of events
git log --oneline
# show a graph of the tree, showing the branch structure of merges
git log --graph --decorate --pretty=oneline --abbrev-commit
# add --all to show all branches
# show all the commits in a branch that are not in HEAD. e.g. show all commits that are in master but not merged into the current feature branch yet.
git log ..master
# prints a complete list of previous operations.
git reflog
### search git history ###
# to find all commits where commit message contains given word, use
git log --grep=word_to_search_for
# to search all of git history for a string
git log -Sword_to_search_for
# this will find any commit that added or removed the string password. Here are a few options:
#
# -p: will show the diffs. If you provide a file (-p file), it will generate a patch for you.
# -G: looks for differences whose added or removed line matches the given regexp, as opposed to
# -S, which "looks for differences that introduce or remove an instance of string".
# --all: searches over all branches and tags; alternatively, use --branches[=<pattern>] or --tags[=<pattern>]
#
# same via blame if the file is known
git blame filename | less
# search the output for the desired code
# search for a specific path
git log -- foo/bar/file
# search for a partial match in a path
git log -- *foo*
# search and exclude certain paths from the results:
# exclude subfolder foo
git log -- . ":(exclude)foo"
# exclude several subfolders
git log -- . ":(exclude)foo" ":(exclude)bar"
# exclude specific elements in that subfolder
git log -- . ":(exclude)foo/bar/file"
# exclude any given file in that subfolder
git log -- . ":(exclude)foo/*file"
git log -- . ":(exclude,glob)foo/*file"
# make exclude case insensitive
git log -- . ":(exclude,icase)FOO"
# which branch contains a specified sha key
git branch –contains SHA
# find the last commit of a given branch
git log -n 1 origin/branch-name
# to get this information for all tags/branches
git ls-remote git://github.com/<user>/<project>.git
###############
### merging ###
###############
# merge branch_b into branch_a
git checkout branch_a
git merge --no-edit branch_b
git push
#
# if branch_b isn't local yet and you get the error:
# merge: branch_b - not something we can merge
# run the following first and the repeat the above
git checkout branch_b
######################
### cherry picking ###
######################
# choose a commit rev from one branch (e.g. PR) and merge it the current checkout
git show <commit> # check that this is the right rev
git cherry-pick <commit> # merge it into the current checkout
git push
# to merge a range of commits:
git cherry-pick <commit1>..<commitN>
# cherry picking parts of a commit (only sections/hunks and not whole files)
git cherry-pick -n <commit> # get your patch, but don't commit (-n = --no-commit)
git reset # unstage the changes from the cherry-picked commit
git add -p # make all your choices (add the changes you do want)
git commit # make the commit!
#
# similar to the above 4 commands - interactive picking (-p == --patch)
git checkout -p <commit>
# and if only changes for specific files are wanted:
git checkout -p <commit> -- path/to/file_a path/to/file_b
# cherry-pick another git repo (can use sha1 instead of FETCH_HEAD)
git fetch <remote-git-url> <branch> && git cherry-pick FETCH_HEAD
# abort the started cherry-pick process, which will revert to the previous state
git cherry-pick --abort
# cherry-picking from another repo
git remote add other https://github.com/microsoft/Megatron-DeepSpeed
git fetch other
git cherry-pick <rev>
# cherry-picking github PR requests
# 1. add to .git/config: fetch = +refs/pull/*/head:refs/remotes/origin/pr/*, so that it looks like (last line) - need to do only once per checkout
[remote "origin"]
url = [email protected]:fastai/git-tools.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
# 2. sync the PRs
git fetch origin
# 3a. cherry pick from the PR
git cherry-pick <rev>
# 4b. or checkout a particular PR
git checkout pr/999
#
# step 1 can be automated with:
#!/usr/bin/env bash
# adds fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
git remote -v | grep fetch | grep github | \
while read remote url _; do
if ! git config --get-all "remote.$remote.fetch" | grep -q refs/pull
then
git config --add "remote.$remote.fetch" \
'+refs/pull/*/head:refs/remotes/'"$remote"'/pull/*'
fi
done
### Merge Git Updates with local changes
### checkouts
# checkout a specific commit
git checkout <sha1>/or-short-hash
### overwrite local changes ###
# If you want to remove all local changes from your working copy, simply stash them:
git stash push --keep-index
# or if it's important you can name it
git stash push "your message here"
# to merge the local changes saved with 'git stash push' after 'git pull'
git stash pop
# (but that seems to not work well for jupyter notebooks)
# if the merge fails, it doesn't get removed from the stash.
# once merge conflict is manually removed, need to manually call:
git stash drop
# to merge a specific stash by the number
git stash apply n
git stash apply stash@{n}
# if there was a conflict from git stash pop (which requires merge):
# 1. edit the conflict file
# 2. git add conflict_file
# git diff --cached is now needed
# or can repeat
# git stash && git stash pop
# and now a normal git diff will work.
#
# also can unstage the stash pop merge with
git reset
# If you don't need them anymore, you now can drop that stash:
git stash drop
# to override all local changes and does not require an identity:
git reset --hard
git pull
# or:
git checkout -t -f remote/branch
git pull
# Discard local changes for a specific file
git checkout dirs-or-files
git pull
# maintain current local commits by creating a branch from master before resetting
git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master
# pull from upstream and accept all changes blindly
git pull --strategy theirs
# list existing stashes
git stash list
# view stash diff
# latest stash
git stash show -p
# specific stash
git stash show -p stash@{0}
#
# show the contents of each stash with one command
git show $(git stash list | cut -d":" -f 1)
# diff against a specific stash
git diff stash@{0}
# diff against a specific stash's filename
git diff stash@{0} my/file.ipynb
# diff 2 stashes:
git diff stash@{0}..stash@{1}
# XXX: to explore
https://stackoverflow.com/questions/16444720/how-do-i-pop-git-stash-without-triggering-an-auto-merge
git stash branch <branchname> [<stash>]
# check out nbdime - diffing and merging of Jupyter Notebooks
https://nbdime.readthedocs.io/en/stable/ see jupyter.txt for notes
### check out a specific branch ###
git clone https://github.com/vidartf/nbdime -b optimize-diff2
### don't page output --More-- on systems that can't support interactive outputs, like CIs
git --no-pager diff ...
##############
### HF Hub ###
##############
# main doc
https://huggingface.co/docs/hub/repositories-pull-requests-discussions
# to create a PR branch and push into it
1. first go into Community tab
2. click on New pull request - follow the instructions
# to fetch and update a PR branch
git fetch origin refs/pr/1:pr/1
git checkout pr/1
# Do your changes
git add .
git commit -m "Add your change"
git push origin pr/1:refs/pr/1
##############
### GitHub ###
##############
### add collapsible comments (e.g. a huge log file)
<details>
<summary>Full log</summary>
<pre>
log file dump here
</pre>
</details>
### detach / break a fork connection ###
to make a fork into a non-fork on github:
If you want to preserve metadata like issues, project boards, forks, etc. go here: https://support.github.com/contact?tags=rr-forksm and type in “detach fork from parent repo.” It should ask you if you’d like to use the GitHub Virtual Assistant to solve your problem. Accept and the virtual assistant will prompt you for the repo url, and then perform the action for you.
### delete a fork ###
1. Go to github.com/stas00/[FORKED-REPO]/
2. Hit Settings
3. Scroll down and hit [Delete this repository]
# find active forks - when researching if someone made improvements over the original repo
# this one doesn't really show if there are any changes
https://github.com/techgaun/active-forks
https://techgaun.github.io/active-forks/index.html
# find the origin of the given fork
# the last html_url is the one of the fork origin (there are 6 of those in the response)
curl -s https://api.github.com/repos/$fork_user/$repo_name | grep html_url | tail -1
### sync master fork with master repository ###
### Syncing a Fork method ###
https://help.github.com/articles/syncing-a-fork/
# step 1. Configuring a remote for a fork
git clone git://github.com/stas00/fastai sync
cd sync
git remote -v
git remote add origin [email protected]:stas00/transformers.git
git remote add upstream [email protected]:huggingface/transformers.git
git remote -v
# non-SSH (password auth) version
# git clone https://github.com/stas00/fastai sync
# git remote add upstream https://github.com/fastai/fastai.git
# step 2. Syncing a fork
git fetch upstream
git checkout master
git merge --no-edit upstream/master
git push --set-upstream origin master
# or one line:
git fetch upstream; git checkout master; git merge --no-edit upstream/master; git push --set-upstream origin master
# to update a branch made from that fork:
git checkout branch
git merge origin/master
git push
### XXX: this method I haven't tried yet ###
### Syncing a one person fork method:###
git clone https://github.com/stas00/fastai sync2
cd sync2
git remote set-url origin [email protected]:fastai/fastai
git remote set-url origin --push [email protected]:stas00/fastai
#####################
### pull requests ###
#####################
### fetch a remote PR into your local repo ###
# Method 1: hub
# advantageous as it is set to track the original branch on the fork,
# so that if mor e commits are added, they can be `git pull`ed.
# it uses the same branch name as the original PR
git clone https://github.com/fastai/fastai
cd fastai
hub checkout https://github.com/fastai/fastai/pull/970
# now can check the diff
git diff master
# Method 2: does not commit changes, to see what files are modified and what's changed in them
# from github PR info:
# https://github.com/fastai/fastai/pull/1369
# USERID wants to merge 28 commits into REPONAME:master from USERID:BRANCH
git checkout -b pr-1369
git pull --no-commit https://github.com/USERID/REPONAME.git BRANCH
# Method 3: alias that checks out and switches to pr branch
git pr <id>
# delete all the pull requests created with git pr
git pr-clean #
#
git config --global --add alias.pr '!f() { git fetch -fu ${2:-upstream} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f'
#and
git config --global --add alias.pr-clean '!git checkout master ; git for-each-ref refs/heads/pr/* --format="%(refname)" | while read ref ; do branch=${ref#refs/heads/} ; git branch -D $branch ; done'
# but requires that the upsteam is set, e.g.:
git remote add upstream https://github.com/huggingface/transformers.git
# Method 4: git-pr is in the git-extras package
# it switches to a branch with the PR ID
cd git-repo
git-pr PR_ID
# Method 5: (doesn't get updated with new commits to PR)
git fetch origin pull/ID/head:BRANCHNAME
# - ID is the pull request id
# - BRANCHNAME is the name of the new branch that you want to create.
# Next, checkout the newly created branch
git checkout BRANCHNAME
# Method 6: optimized for quickly checking out a PR branch for when it's done often
# in a given project. The first 2 steps only need to be done once per clone.
#
# 1. Locate the section for your github remote in the .git/config file. It looks like this:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = [email protected]:joyent/node.git
#
# 2. Now add the line fetch = +refs/pull/*/head:refs/remotes/origin/pr/* to this section. Obviously, change the github url to match your project's URL. It ends up looking like this:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = [email protected]:joyent/node.git
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
#
# 3. Now fetch all the pull requests:
$ git fetch origin
From github.com:joyent/node
* [new ref] refs/pull/1000/head -> origin/pr/1000
* [new ref] refs/pull/1002/head -> origin/pr/1002
* [new ref] refs/pull/1004/head -> origin/pr/1004
* [new ref] refs/pull/1009/head -> origin/pr/1009
...
#
# 4. To check out a particular pull request:
$ git checkout pr/999
Branch pr/999 set up to track remote branch pr/999 from origin.
Switched to a new branch 'pr/999'
# Method 7: patch-method - requires no checked out repo.
# add .patch to the PR url, download it and apply it to a desired branch:
cd cordova-plugin-media
wget https://github.com/apache/cordova-plugin-media/pull/120.patch
git checkout -b new-branch-pr-210
patch -p1 < 120.patch
#############################
### making a pull request ###
#############################
# example with new branch named: accuracy_np
*** Important - must make a new clone for each new branch ***
# 1. Sync the forked version with master
see above
# 2. clone the main repository fork
# (or if it hasn't been done yet fork it first on github by going to
# github.com:fastai/fastai)
#
# moreover - make sure that the repository fork is up-to-date by syncing it
#
git clone git://github.com/stas00/fastai branch_name
cd branch_name
git remote rm origin
git remote add origin [email protected]:stas00/fastai.git
# 3. create a branch
git checkout -b branch_name
# if the master sync has since updated:
git rebase master
# old:
#git checkout master
#git pull
#git checkout -b branch_name
# 4. edit code and commit changes
# may validate the changes:
jsonlint-php lesson7-cifar10.ipynb
# commit
git commit -a
# 5. push the changes into the branch
git push origin branch_name
# 6. go to github and make pull request
https://github.com/stas00/fastai/tree/branch_name/courses/dl1
and click [Pull Request] on the right upper corner
### update an open PR ###
# if the upstream master changes impact PR after PR has been submitted we need to rebase
## Method 1
# prep (from within an existing checkout)
# 1. sync my master fork
git fetch upstream; git checkout master; git merge --no-edit upstream/master; git push --set-upstream origin master
#
# 2. get the desired PR
git checkout my-pr-branch # git checkout -
# or checkout the specific PR number
gh pr checkout 6260
# if getting rejected - because previously checked out a different branch but with the same name -
# e.g. with patch-1, force reset:
gh pr checkout 6260 --force
# important: this will overwrite any commits you have locally that aren't present on the remote branch.
# Or pass in a different branch name to checkout the PR to:
gh pr checkout 6260 -b pr-6260
# 3. rebase to my fork
git pull --rebase
git merge origin/master
git push
# Method 2. https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request
#
# it seems to be problematic as it rebases one commit at a time, which can cause multiple collisions
#
# this example is for a fork of https://github.com/huggingface/transformers.git
# setup upstream if it is not there already
# git remote add upstream https://github.com/huggingface/transformers.git
# rebase
git fetch upstream
git rebase upstream/master
# force-push to update your pull request
git config --global push.default simple
git push -f
# Method 3. (incomplete - needs work)
git fetch upstream
git merge --squash upstream/master
### Squash many commits into one before PR
## method A. new branch method
# when working on a complex branch, there will be a lot of commits - since PR
# squashes them anyway, it's the cleanest to squash them all into one commit
# just before doing the PR onto a new branch - and keeping the old branch with
# all the separate commits for later reference. Here is the recipe:
# https://stackoverflow.com/a/32484278/9201239
# If you are on a remote branch (called `feature-branch`) cloned from a Golden Repository (`master`)
# 1. Checkout the golden repo (master)
git checkout master
# 2. Create a new branch from it (golden repo) as follows
git checkout -b dev-branch
# 3. Squash merge with your local branch that you have already
git merge --squash feature-branch
# 4. Commit your changes (this will be the only commit that goes in dev-branch)
git commit -m "My feature complete"
# 5. Push the branch to your local repository
git push origin dev-branch
## method B. interactive way (complex and time consuming)
# https://stackoverflow.com/a/5189600/9201239
# run
git rebase -i <after-this-commit>
# replace "pick" on the second and subsequent commits with "squash" or "fixup",
git commit
git push -f
# <after-this-commit> is either the SHA1 hash or the relative location from the
# HEAD of the current branch from which commits are analyzed for the rebase
# command. For example, if the user wishes to view 5 commits from the current
# HEAD in the past the command is:
git rebase -i HEAD~5.
## method C. soft reset
git reset --soft HEAD~3
git commit
git push -f
# squashes the last three commits into a single new commit in the same way. The
# soft reset just re-points HEAD to the last commit that you do not want to
# squash. Neither the index nor the working tree are touched by the soft reset,
# leaving the index in the desired state for your new commit (i.e. it already
# has all the changes from the commits that you are about to “throw away”).
# this can be added as a global "squash" alias from bash:
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
# Usage:
git squash N
# which automatically squashes together the last N commits, inclusive.
#
# The resultant commit message is a combination of all the squashed commits, in
# order. If you are unhappy with that, you can always git commit --amend to
# modify it manually.
### PR search
# find PR by branch name. e.g. find all the PRs that were originated from branch "patch-1"
is:pr author:@me head:patch-1
##################
### GitHub CLI ###
##################
# create PR from the current branch
gh pr create
# dump the status of all the open PRs on github for the current project
gh pr status
gh pr create
################
### branches ###
################
# show local and remote branches
git fetch --all
git branch -a
# get default branch
git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
# a much more complicated version that requires repo user + name
curl -s https://api.github.com/repos/${repo_user}/${repo_name} | jq --raw-output .default_branch
# delete branch (after switching out of it, e.g. git checkout master)
git branch -d branch_name
# if it wasn't pushed and no longer needed (careful!)
git branch -D branch_name
# branch delete via github - after the branch has been merged into the master upsteam, can now delete the branch in my fork at github.com
1. https://github.com/stas00/fastai/branches
# or go to https://github.com/stas00/fastai/ (and click [NN branches] above [New pull request] button
2. hit the trash button next to the branch to remove
# List branches that ever merged or not yet merged to current branch.
# It’s a useful check before any merging happens
git branch --merged
git branch --no-merged
# delete branches that have already been merged on master
git branch -r --merged | sed '/develop\|master\|HEAD\|upstream/d' | sed 's/.*\///' | xargs git push --delete origin
# this doesn't seem to get branches that were created directly on github (usually automatically named as `patch-X`)
#
# another variation (untested)
git fetch -p
git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs git branch -d
# switch back to last branch (like 'cd -')
git checkout -
# @{-1} is a way to refer to the last branch you were on. '-' is shorthand for @{-1}
# git branch --track mybranch @{-1}, git merge @{-1}, and git rev-parse --symbolic-full-name @{-1} would work as expected.
# compare two branches in the same repo
git diff --stat --color master..branch_name
# or:
git difftool -d master branch_name
# find the diff from their common ancestor to test, you can use ... instead of ..:
git diff --stat --color master...branch_name
# to compare just specific files
git diff branch1 branch2 -- myfile1.js myfile2.js
# to compare a sub-directory or specific files across different commits
git diff <rev1>..<rev2> -- dir1 file2
# compare rev with one revision before
git diff <rev>~ <rev> -- dir1 file2
# show only names of changed files
git diff --name-only ...
# compare two branches in different repos (e.g. original and github fork)
# given 2 checkouts /path/to/repoA and /path/to/repoB
cd /path/to/repoA
GIT_ALTERNATE_OBJECT_DIRECTORIES=/path/to/repoB/.git/objects git diff $(git --git-dir=/path/to/repoB/.git rev-parse --verify HEAD) HEAD
# another way using GUI with meld (apt install meld)
meld /f1/br/stas00/master/ /f1/br/fastai/master
# find the most recent ancestor between two branches, usually the branching point:
git merge-base master origin/branch_name
# in the case of the currently checked out branch, it's just
git merge-base master HEAD
@
# same, but returns a short rev instead of the long one
git rev-parse --short $(git merge-base master origin/branch_name)
# in the case of the currently checked out branch, it's just
git rev-parse --short $(git merge-base master HEAD)
#
# alternative (doesn't always work, e.g. fails with `git-pr` and `gh pr checkout`)
git merge-base --fork-point master origin/branch_name
# note that 'git merge-base' returns no output once that branch has been merged to master.
# to find the oldest common ancestor (when multiple merges happen from one branch to another)
# https://stackoverflow.com/a/4991675/9201239
# Given this find B
A - B - D - F - G <- "master" branch (at G)
\ \ /
C - E --' <- "topic" branch (still at E)
# replace topic with the branch name
diff -u <(git rev-list --first-parent topic) \
<(git rev-list --first-parent master) | \
sed -ne 's/^ //p' | head -1
# if it's the current branch, it's just HEAD
diff -u <(git rev-list --first-parent HEAD) \
<(git rev-list --first-parent master) | \
sed -ne 's/^ //p' | head -1
# same w/o sed:
diff --changed-group-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1
# and it doesn't always work either
# diff between the branching point and the HEAD of the branch
git diff $(git merge-base --fork-point master origin/branch_name)..origin/branch_name
# in the case of the currently checked out branch, it's just
git diff $(git merge-base --fork-point master HEAD)..HEAD
# get modified files between current state and the branching point (doesn't matter whether the
# files have been staged, pushed or locally modified). only requires that the files are under git.
def_branch=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); git diff $(git merge-base $def_branch HEAD)
# or
git diff $(git merge-base $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@') HEAD)
# the old one no longer works on default branches that are 'main'
# git diff --name-only $(git merge-base master HEAD)
#
# handy aliases based on this
alias brdiff2="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); git diff \$(git merge-base \$def_branch HEAD)"
alias bremacs2="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); emacs \$(git diff --name-only \$(git merge-base \$def_branch HEAD)) &"
alias brfiles2="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); git diff --name-only \$(git merge-base \$def_branch HEAD)"
#
# the problem is that they often include merged files from rebasing as well, so to get just the
# changes of this branch excluding any rebased main/master, we use:
# git diff --name-only origin/main... or git diff --name-only origin/master...
# which gives:
alias brdiff="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); git diff origin/\$def_branch..."
alias bremacs="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); emacs \$(git diff --name-only origin/\$def_branch...) &"
alias brfiles="def_branch=\$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'); git diff --name-only origin/\$def_branch..."
# commits between the branching point and the HEAD of the branch
git log --oneline $(git merge-base --fork-point master origin/branch_name)..origin/branch_name
# for the currently checked out branch:
git log --oneline $(git merge-base --fork-point master HEAD)..HEAD
# find branches the commit is on
git branch --contains <commit>
# find when a commit was merged into one or more branches.
# https://github.com/mhagger/git-when-merged
git when-merged [OPTIONS] COMMIT [BRANCH...]
### branch tracking ###
# branch tracking is set in the local git checkout (not in the upsteam repo)
#
# e.g to set the tracking to master:
git push --set-upstream origin master
# or to a branch name
git push --set-upstream origin my-branch-name