git recipes

Over time I've been collecting command snippets for doing various things. These might be some simple things but not necessarily something that I do every day. This way I don't need to remember them after a few weeks or moths, nor figure them out nor find them on the Internet every time, I just copy-paste them from my recipes collection. Various people who have seen my collection have asked for a copy. So I've figured that I can as well share them in general, they will be here under the tag recipes (and I've already had a post about the clustering commands tagged with it).

This  installment is about git:

 # Git book
 https://progit.org/
 # Basic Git
 https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository
 # Git Branches
 https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell
 # working with remote repositories
 https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes

# set the editor
 set GIT_EDITOR=gvim

# create the git repo and initial commit for an existing code base
 cd myproject
 git init --separate-git-dir=c:\git\myproject
 git add .
 git commit -a
 # to restore the .git file pointing to a separate dir, put in it:
 gitdir: c:/git/myproject
 # To move the work tree, edit c:\git\myproject\config and change the worktree
 # location there.
 # in push and pull USE THE WORKING DIRECTORY, not the separate git dir!!!

# show the location of the remote branches (origin)
 git remote -v
 # show how the local and remote branches are connected
 git remote show origin

# set the push mode to push only the current branch
 git config push.default simple
 # set the mode to push all the branches to the matching ones
 git config push.default matching

# set to use the access token
# Set up a Personal Access Token (PAS) in VSO https://project.visualstudio.com/_details/security/tokens (much like github with 2FA)
 git config credential.https://project.visualstudio.com.username me@domain.com
 git config credential.https://project.visualstudio.com.helper store
 # then do "git remote show origin" and enter the password once manually,
 # it will be stored in ~\.git-credentials
 # Or enter the line there manually, like:
 https://me%40domain.com:TextOfTheAccessToken@project.visualstudio.com

# to see all branches, including the ones that were pulled but not checked out
 git branch -a

# to undo a merge
 git reset --hard <last_old_change>

# to merge one change
 git cherry-pick <change_id>
 # to remember the conflict resolutions from cherrypicking, when cherrypicking
 # to multiple branches
 git config --global rerere.enabled true
 # control the rerere cache
 git rerere

# show the messages of last commits of every branch
 git branch -vv

# merge a difference between 2 branches onto the 3rd one:
 # pick the changes that are on client but not on server branch and copy them to the master branch
 git rebase --onto master server client

# Show the list of commits differing between two branches - what is present on origin/master but missing on issue54
 git log --no-merges issue54..origin/master
 # Show the list of commits on branch "contrib" since the branch was started off master
 git log contrib --not master
 # find the base commit on which the branch "contrib" started off "master"
 git merge-base contrib master
 # show the diff since the branch "contrib" was started off "master"
 # https://git-scm.com/book/en/v2/Distributed-Git-Maintaining-a-Project
 git diff master...contrib

# Cloning a repository:
 cd c:\work
 git clone -l --separate-git-dir c:\git\myproject2 --no-hardlinks c:\work\myproject myproject2
 # "git pull" is a combination of "git fetch" and "git merge"
 git pull origin # or just git pull
 # the safer option that keeps moving the local commits to the end of the chain is
 git pull --rebase
 # (the downside is that it can create a whole lot of merge conflict pain?)
 # or to make this behavior default set
 git config --global pull.rebase true

# push one branch to origin, creating it there
 # -u sets the upstream connection between the branches
 git push -u origin featureA
 git push --set-upstream origin nano_pr
 # Push a local branch to a differently named remote branch (refspec)
 # local featureB to origin/featureBee
 # -u sets the upstream connection between the branches
 git push -u origin featureB:featureBee

# Create a branch off an origin branch
 git fetch origin
 git checkout -b featureB origin/master

# Merge a branch, squashing all its commits into one commit (and losing the
 # proper connection to that branch, so it's dangerous; after that you couldn't
 # merge from master to featureB any more, and the branch featureB becomes
 # essentially dead)
 git merge --squash featureB

# How to merge with squashing but preserving the dependencies between branches:
 # suppose we have the branch "work". Create another intermediate branch "work_pr"
 # for submitting the PRs through it.
 git checkout work_pr
 git merge --squash work
 # after that, do:
 git commit -a # edit the message
 git merge work # needed to record the proper merge, to not have the same changes appear the second time
 git checkout work
 git merge work_pr # record the proper history the other way around
 git checkout work_pr
 # now push work_pr and create a PR from it

# Create a patch (-M includes the renames)
 git format-patch -M origin/master

# apply a patch (similar to patch -p1 but can handle renames and deletes in git patch format)
 git apply /tmp/patch-ruby-client.patch
 # apply a patch including the commit comments, and/or multiple patches from a mailbox file
 git am 0001-limit-log-function.patch
 # same but smarter, taking in account the original version
 git am -3 0001-limit-log-function.patch

# Create a local branch that tracks the remote branch from origin
 # (see https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches )
 git checkout -b serverfix origin/serverfix
 # or the same
 git checkout --track origin/serverfix

# save the current state of the branch as a tar file:
 git archive master --prefix='project/' | gzip > master.tgz

# see https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
 # log of recent actions
 git reflog
 # show the difference from the last commit
 # "^" means the parent of the named commit, if multiple parents (such as in a merge),
 # "^2" can be used for the second parent.
 git diff "HEAD^"
 # Same, but "~2" means "grandparent" etc. Can also write "^^" for grandparent, etc.
 git diff HEAD~

# Show the commits done on experiment after it branched off master
 git log master..experiment
 # Show the commits on both branches since they diverged
 git log master..experiment
 # Same and also show which commit is on which branch
 git log --left-right master...experiment

# remove the unstaged files
 # -x includes the ignored files into cleaning
 # -d removes the directories too
 # -i asks interactively
 git clean -f -x -d

# search through the code base, printing the line numbers
 git grep -n gmtime_r
 # show just the count f matches per file
 git grep --count gmtime_r
 # show along with the function name where the item is found, as parsed by git
 git grep -p gmtime_r *.c
 # other grep output options: --break, --heading
 # --and looks for multiple items on the same line
 # May specify a tag or branch as an argument
 git grep --break --heading \
 -n -e '#define' --and \( -e LINK -e BUF_MAX \) v1.8.0

# find the commit where the ZLIB_BUF_MAX was added or removed
 git log -SZLIB_BUF_MAX --oneline
 # find commits with changes to a particular function (as parsed from the source code)
 git log -L :git_deflate_bound:zlib.c
 # find commits by a regex range of changes
 git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c