- 1 workflow
- 2 git grep related
- 3 Tips
- 3.1 frequently used
- 3.2 git pull autostash
- 3.3 rebasing using git gui
- 3.4 Generate diff with no context
- 3.5 Get current branch name
- 3.6 show modified files in the current directory only
- 3.7 multiple repositories
- 3.8 Diff word by word
- 3.9 delete branches
- 3.10 Migrate from sourceforge to github
- 3.11 git and vimdiff
- 3.12 viewing diffs
- 3.13 merge a development branch into master
- 3.14 gitlab
- 3.15 pruning
- 3.16 what files changed between two branches
- 3.17 time zone of the committer
- 3.18 list of commits from an author
- 3.19 checkout a file with a hash
- 3.20 external links
- 4 git diff related
- 5 Commits related
- 6 Tasks
- 7 git commands usage
- 8 branches related
- 9 Configuration related
- 10 dummy
- 10.1 git bash
- 10.2 detaching HEAD
- 10.3 relative refs
- 10.4 branch forcing
- 10.5 reversing changes
- 10.6 interactive rebase
- 10.7 Exclude .git directory from grep searches
- 10.8 exclude .git directory when comparing two repos
- 10.9 ssh key generation
- 10.10 debug slowness in git bash
- 10.11 commit only some parts of files
- 10.12 books
Updating feature branch with the latest development branch
tags | bring feature branch up to date with development branch
- User 1 raised a merge request to merge feature1 to development branch
- Before the merge request is accepted, development branch is updated by User 2
- Say you forked from development branch a while ago to work on a feature and created a branch called "feature1".
- After a while, development branch might have progressed and may have new changes added to it.
- Bring the feature1 branch up to date with the latest development branch.
Get the latest versions of development and feature branches in the local repository.
git checkout development git pull git checkout feature1 git pull
Merge development branch into the feature branch and resolve any conflicts that may arise.
git merge development
Push the changes to the remote.
Note:- The "git merge development" command works even if you have local changes not committed to feature1.
rebase to another branch
To take BranchB and rebase it on top of BranchA
1) Update BranchA to the latest version if needed
git checkout BranchA git pull --rebase --autostash -v origin
2) Merge changes from BranchA into BranchB
git checkout BranchB git rebase --autostash -v BranchA
This effectively makes BranchB look as if it was branched off of BranchA.
You can also use 'git merge' instead of rebase but that will create a merge commit.
git checkout BranchB git merge BranchA
find files containing two words
tags | multiple words
git grep --all-match -e word1 -e word2
will search for all files that contain both the words somewhere in the file (not necessarily on the same line).
git grep --all-match -e <regex1> -e <regex2>
- http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja/ - talks about many other use cases of "git grep"
- https://git-scm.com/docs/git-grep - documentation on "git grep"
search from project root
tags | git grep
git grep pattern -- :/
Solution 2: The git aliases that run shell commands are always executed in the top level directory. So add this to your .gitconfig file:
[alias] # rgrep stands for repo grep rgrep = !git grep
git pull --rebase --autostash -v origin
git pull autostash
git pull --rebase --autostash
The --autostash works only with --rebase. It was introduced in git 2.6 (2015-09-28).
- Explained very well in https://cscheng.info/2017/01/26/git-tip-autostash-with-git-pull-rebase.html
- documentation - https://git-scm.com/docs/git-pull#git-pull---autostash
rebasing using git gui
Q. How to do git pull --rebase using git gui?
A. The trick is to add a custom command in git gui:
Tools -> Add Name: Pull with Rebase Command: git pull --rebase origin Add globally -> check Add
The new command will appear under Tools menu.
Generate diff with no context
git diff -U0
In general, to generate a diff with <n> lines of context, use
git diff -U<n>
git diff --unified=<n>
The default is 3 lines of context.
Get current branch name
Git >= 2.22
git branch --show-current
Git >= 1.7
git rev-parse --abbrev-ref HEAD
Git >= 1.8
git symbolic-ref --short HEAD
git branch | grep \* | cut -d ' ' -f2 git branch | sed -n '/\* /s///p'
show modified files in the current directory only
git status .
or more generally
git status /path/to/dir
works from git 1.7 onwards. Does not work with git 1.6.
Author of myrepos - Joey Hess. His contact info is at https://joeyh.name/contact/
Diff word by word
To diff word by word
git diff --color-words
To set up an alias for it
git config --global alias.wdiff "diff --color-words"
which will add the following lines to ~/.gitconfig
[alias] wdiff = diff --color-words
Once done, "git wdiff" will do the same thing as "git diff --color-words"
To delete a remote branch
git push <remote_name> -d <branch_name>
To delete a local branch
git branch -d <branch_name>
Migrate from sourceforge to github
The instructions to move a git repository from sourceforge to github are clearly laid out in https://help.github.com/articles/importing-a-git-repository-using-the-command-line/ .
Login into github website create a new repository called sampleusage: https://github.com/KamarajuKusumanchi/sampleusage git clone --bare ssh://firstname.lastname@example.org/p/sampleusage/git sampleusage-git cd sampleusage-git git push --mirror https://github.com/KamarajuKusumanchi/sampleusage.git cd .. rm -rf sampleusage-git
To get a local copy
git clone email@example.com:KamarajuKusumanchi/sampleusage.git cd sampleusage git config user.name "Kamaraju S. Kusumanchi" git config user.email "firstname.lastname@example.org"
Sample work flow once it is all done
git add dummy_file git commit -m "dummy commit message" git push -u origin master
After making sure that everything on github is working properly, I submitted a ticket to delete the original sourceforge project.
git and vimdiff
- http://usevim.com/2012/03/21/git-and-vimdiff/ - contains tips on how to effectively use git, vimdiff and vim together.
- http://365git.tumblr.com/post/474079664/whats-the-difference-part-1 - explains how to diff between HEAD, Index and Working tree
merge a development branch into master
- pricing - https://about.gitlab.com/gitlab-com/
- explore project - https://gitlab.com/explore
- compare terminology across different platforms - https://about.gitlab.com/2016/01/27/comparing-terms-gitlab-github-bitbucket/
To list the branches that are merged into master
git branch --merged master
To list the branches that are merged into HEAD (i.e. tip of the current branch)
git branch --merged
To list the branches that were not merged
git branch --no-merged
By default this only applies to local branches. Use -a to show both local and remote branches; -r to show only remote branches.
To delete all local branches that have been merged into master
git branch --merged | grep -v '\* master' | xargs -n1 git branch -d
To delete all local branches that have been merged into the current branch
git branch --merged | grep -v '^\*' | xargs -n1 git branch -d
what files changed between two branches
To compare the current branch against master
$ git diff --name-status master
To compare any pair of branches
$ git diff --name-status firstbranch..secondbranch
time zone of the committer
git cat-file -p <commit-id>
Will show the entire commit object. It will contain two lines like this:
author Foo Bar <email@example.com> 1398017575 -0400 committer Foo Bar <firstname.lastname@example.org> 1398017575 -0400
As you can see, the timezone info follows the Unix-epoch timestamps.
Note that the timezone is something set by the user himself on the client. So it can be easily spoofed by the user if he desires to.
git log --author=bob git log --email@example.com
checkout a file with a hash
git checkout [hash] -- [file]
-  - Combine two files into one while preserving line history in git
-  - Explains how to work with git submodules. Easy to read, contains example.
- A few git tips you didn't know about
-  - The section on commit message templates is pretty interesting.
git diff only list filenames
git diff --name-status otherbranch
git diff --name-status [SHA1 [SHA2]] git diff --name-status mybranch..otherbranch git diff --name-only SHA1 SHA2 git diff --name-only HEAD~10 HEAD~5 git log --name-status --oneline [SHA1..SHA2] git diff --stat HEAD~5 HEAD git diff --numstat HEAD~5 HEAD
Ref:- https://stackoverflow.com/questions/1552340/how-to-list-only-the-file-names-that-changed-between-two-commits - contains many other commands that are slightly different to do slightly different things.
what changed in a commit
git diff COMMIT^!
which is a shortcut for
git diff COMMIT~ COMMIT
git diff N last commits
git diff HEAD~N
number of commits
To get a commit count for a revision (HEAD, master, a commit hash):
git rev-list --count <revision>
To get the commit count across all branches:
git rev-list --count --all
check commits where a file has changed
tags | show commits on a single file
To list the last 3 commits that changed a file
git log -n3 --follow -- filename
Change last commit message
git commit --amend
Add a file to the last commit
git add missed-file.txt git commit --amend
Remove a file that was accidentally committed
- See point (3) in https://about.gitlab.com/2018/08/08/git-happens/ which uses "git reset" to do this.
discard all changes in working directory
git checkout -- .
Notes: It will not remove the untracked files.
discard last commit
git reset --hard HEAD~1
update all repositories in a directory
Download the following scripts:
- update_git_repos.sh - https://github.com/KamarajuKusumanchi/rutils/blob/master/bin/update_git_repos.sh
- git_shelf.sh - https://github.com/KamarajuKusumanchi/rutils/blob/master/bin/git_shelf.sh
- git-up - https://github.com/KamarajuKusumanchi/rutils/blob/master/bin/git-up
and put them in a directory where the shell can find them. Then run
It works by calling git_shelf.sh which applies a given "git operation" on all the git repos under a directory. In this case, it is invoked as
git_shelf.sh /path/to/dir up
so it calls "git up" on all directories under /path/to/dir.
Since there is no standard "git up" command, it calls the git-up script.
A barebones solution would look like
for i in *; do echo $i; if [ -d "$i" ]; then cd $i; git up; cd ..; fi done
But the git_shelf.sh approach is better as it generalizes for any git operation. For example to search all git repos that have the word foo and bar, I use
git_shelf.sh /path/to/dir grep -i --all-match -e foo -e bar
or more simply
grep_git_repos.sh /path/to/dir -i --all-match -e foo -e bar
where grep_git_repos.sh is https://github.com/KamarajuKusumanchi/rutils/blob/master/bin/grep_git_repos.sh
checkout previous N versions of a file
/* Todo:- Migrate contents of https://malayamaarutham.blogspot.com/2011/08/extract-historical-versions-of-file.html to this wiki and delete that blog post */
git commands usage
git stash drop - Remove a single stash.
git stash clear - Remove all the stash entries.
Documentation - https://git-scm.com/docs/git-stash
git cherry-pick <Commit1> <Commit2> <...>
- https://learngitbranching.js.org/ -> Moving Work Around -> 1: Cherry-pick Intro
Check commits between two branches
git log branch1..branch2
tags | show commits between two branches
rename a branch locally and remotely
git checkout <old_name> git branch -m <new_name> git push origin -u <new_name> git push origin --delete <old_name>
rename a local branch
To rename the current branch
git branch -m <newname>
To rename a branch while in another branch
git branch -m <oldname> <newname>
By default when you push the new branch to the remote, it will add it as a new branch and will not delete the old branch. See https://stackoverflow.com/questions/6591213/how-do-i-rename-a-local-git-branch if you want to rename the branch on the remote while doing the push.
Configure http proxy
git config --global http.proxy http://login:firstname.lastname@example.org:port
git config settings
To check which config comes from which file
git config --list --show-origin
git config --system -l
tags | where is a setting coming from
cache username and passwords
Git credential storage for Windows:
- Git's built-in credential storage for Windows.
- provides single-factor authentication support working on any HTTP enabled git repository.
git config --global credential.helper wincred
- Provided by the Git Credential Manager for Windows (GCM)
- provides multi-factor authentication support for Azure DevOps, Team Foundation Server, GitHub, and Bitbucket.
git config --global credential.helper manager
- Project website: https://github.com/Microsoft/Git-Credential-Manager-for-Windows
- no longer maintained; Use GCM instead.
- succeeded by GCM
- Windows Credential Store for Git
- Project website: https://gitcredentialstore.codeplex.com/
default location of global git ignore file
Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a file specified by core.excludesFile in the user’s ~/.gitconfig. Its default value is $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore is used instead.
where to put git ignore file
- https://help.github.com/articles/ignoring-files/ - very well explained, brief and to the point.
"Git for Windows" used to be developed using the development environment called "msysGit", but roughly coinciding with Git 2.1, msysGit was superseded by a new development environment.
Ref:- https://github.com/git-for-windows/git/wiki/FAQ -> "What is the relationship between Git for Windows and msysGit?"
Detaching HEAD just means attaching it to a commit instead of a branch. Say we have this beforehand:
HEAD -> master -> C1
git checkout C1
and now it is
HEAD -> C1
- Move upwards one commit at a time with ^
- Move upwards a number of times with ~<num>
git branch -f master HEAD~3
moves (by force) the master branch to three parents behind HEAD.
Two primary ways: git reset, git revert.
Sample command using reset
git reset HEAD~1
Since git reset "rewrites history", you can use it for local branches but not for remote branches.
To reverse changes and share those reversed changes with others, use git revert. For example
git revert HEAD
Call the rebase command with the -i option. Sample command
git rebase -i HEAD~4
exclude .git directory when comparing two repos
diff -rq -x .git repo repo_bkp
ssh key generation
ssh-keygen -t ed25519 -C "email@example.com"
public key will be stored in ~/.ssh/id_ed25519.pub
debug slowness in git bash
$ time echo $(__git_ps1)
commit only some parts of files
Git can stage certain parts of files and not the rest. For example, if you make two changes to a file, you can stage one of them and not the other.
git add --patch
git add -i
Ref:- Pro Git by Scott Chacon and Ben Straub -> Chapter 7. Git Tools -> Interactive Staging
- https://openlibrary.org/books/OL27737331M/Pro_Git - Pro Git by Scott Chacon, Ben Straub
It is a very good book and is my go to reference on git.