2/14/2017 - 4:27 PM

git #git

git #git

Git Tips

Recovering after mixed line endings

  • Set the core.autocrlf property either for the repo or globally.
  • Commit all files in your current repo using:
git add . -u
git commit -m "..."
##- Remove every file from Git's index.
##git rm --cached -r .

  • Remove the index using rm .git/index
  • Rewrite the Git index to pick up all the new line endings.
git reset --hard
  • Add all your changed files back, and prepare them for a commit. This is your chance to inspect which files, if any, were unchanged.
git add -u .
  • Ignore messages that read: "warning: CRLF will be replaced by LF in file."
  • Rewrite .gitattributes with git add .gitattributes
  • Commit the changes to your repository.
git commit -m "Normalize all the line endings"

Sparse Checkouts

  • To perform a sparse checkout:
    mkdir repo-dir
    cd repo-dir
    git init
    git remote add -f origin git-repo-uri
    git config core.sparsecheckout true
  • Create and edit .git/info/sparse-checkout. Add one line per directory/files you need to checkout Eg:
  • Now run:
git checkout master
  • Subsequently refresh using:
git read-tree -m -u HEAD

Displaying commit logs

  • Show all logs using: git log
  • Minimal prettified output
git log   --oneline --graph
  • Show files modified in log messages:
git log --name-only
  • Show what changed in file in each commit
git log -p filename
  • log changes not yet merged to parent
git log --no-merges <parentbranch>..

Eg: git log --no-merges master..

  • Searching a log for commits that introduce a pattern:
git log -Sstring 

will show only commits that added or removed the specified string

  • Searching a log for commits that introduce a regex pattern
git log -Gregexpattern
# also:
git log --grep [-i] [-E] 'ext-regex-pattern'
  • Show evolution of a function
git log -L :functionname:filename
  • Show evolution of a file
git log -- filename
  • Other useful log options
    • --author="..." Only show commits made by that author
    • --reverse Show commits in reverse order (Oldest commit first)
    • --after="..." Show all commits that happened after certain date
    • --before="..." Show all commits that happened before certain data
  • Display commits in one branch not present in the other.
    • Example: display commits develop branch that are not present in master
git log master..develop
  • conversely, git log develop..master shows commits in master not merged in develop.
  • This is useful to show what you're about to push to a remote:
git fetch origin
git log origin/master..HEAD
  • Show what happened in a commit
git show <commit>
  • Example: To see the commit object two revs before the latest revision
git show HEAD~2
# or git show HEAD@{2}

Undo changes

  • undo add with git reset to unstage added files
  • revert changed to edited files using git reset --hard HEAD or alternately git checkout .
  • return to a particular point in history using git reset --hard <commit-hash>. All changes made after this commit are discarded.
  • return to a particular point in history using git reset <commit-hash>. Run git add . and git commit to add the changes back to git.
  • return to a particular point in history using git reset --soft <commit-hash>. All changes made after this commit are automatically added, i.e. staged for commit, so you only need to run git commit to add them back in.
  • To revert specific files, use git checkout <commit-hash> <filename> or git checkout <branchname> <filename>

Compare changes

  • Use git diff or git difftool for a more visual diff
  • git difftool -d when used with tools like meld or winmerge which allow full directory diffs
  • To diff current changes:
git diff HEAD
  • To diff against a branch
git diff branchname
  • To view only changed filenames
git diff --stat


git diff --no-commit-id --name-only
  • To run git diff after a git add: git diff --staged

Common branch ops

  • Show file in another branch git show branchname:filename
  • To remove tracking branches that are not present on the remote repo
git remote prune origin
  • Remove local branches that have been merged
# list merged branches
git branch --merged
# Remove these branches
git branch -d ...
  • List unmerged branches git branch --no-merged

  • Show tracking branches git branch -vv

Determining a recent problem commit

  • Use git revert -n <commit>
  • Commit can be HEAD, HEAD~1, HEAD~2, ... to shift to previous revisions
  • This will undo a previous commit or two, allow you to look at the changes, and see which change might have caused a problem.
  • git revert without -n will automatically re-commit reverted files, prompting you to write a new commit message. The -n flag tells git to not commit, since all we want to do is look.

Selective patching/adding

  • git add -i allows interactive staging
  • git add -p allows interactive patching for added files
  • git stash -p allows interactive stashing

Stashing to a new branch

git stash
git stash branch branchname

Fix commits to the wrong branch

  • Undo last commit, but only from the repo, not the local working copy, so your latest changes are still preserved using:
git reset HEAD~ --soft
  • Now stash to a new branch:
git stash
git stash branch branchname
  • If the branch already exists:
git stash
git checkout branchname
git stash pop

Fix commit to master instead of a new branch

git branch newbranchname
git reset HEAD~n --hard # n is the number of commits to undo
git checkout newbranchname # this contains the previous commits from master

Fix commit to master instead of existing branch

git checkout your-branch-name
git cherry-pick master
git checkout master
git reset HEAD~n --hard   # n is the number of commits to undo

Commit all tracked files without staging

git commit -a 

NOTE Files not tracked will not be added

Modifying a commit

  • Fix an incorrect commit message
git commit --amend
  • Add files that should've been there in the previous commit:
git add ...
git commit --amend --no-edit # reuse previous commit msg

Abort commit while editing commit log

  • When git opens vim to open the edit log, exit vim with :cq to make vim exit witha a non-0 exit code. This makes git abort the commit.

Fixup and autosquash to cleanup bad commits

  • If you make a new commit to fix a previous bad commit, you can use
# git add/rm/mv ...
git commit --fixup <badcommit>
git rebase -i --autosquash <badcommit>^

git grep - Search a git tree

  • Use git grep instead of grep -R to search a git tree.
  • To show function names containing a pattern, use -p
  • Eg: git grep -p basename *.sh
  • Use --break and --heading to make the output more readable
  • To search for more than one pattern: -e pattern1 --and -e pattern2
  • To search for more than one pattern ('--or' implied): -e pattern1 -e pattern2
  • To negate a pattern: --not -e pattern1

git push syntax

  • git push [remote-name] [branch-or-tag-to-push]
  • Eg: git push origin master
  • Eg: git push origin v1.0.2

Show remote info

  • git remote show <remotename>
  • Eg: git remote show origin

Show tag info

git show <tagname>

Git Post-install on a new system

Install git flow if necessary

# set proxy before this step if required
git clone https://github.com/petervanderdoes/gitflow-avh.git
cd gitflow-avh
sudo make install

Set up Username/id

git config --global user.name "your name"
git config --global user.email "your@email.id" 

Default push policy

git config --global push.default simple

Default misc global settings (Change to your prefs)

git config --global color.ui auto
git config --global core.editor vim
git config --global diff.tool meld #used by git difftool, use vimdiff if meld is not available
git config --global merge.tool meld #used by git mergetool, use vimdiff if meld is not available

Default misc repo-specific settings (Change to your prefs/repo)

# For repos with submodules
git config status.submodulesummary 1
git config diff.submodule log

crlf policy

git config --global core.autocrlf input
# Windows
# git config --global core.autocrlf true

Long filenames on Windows

  • To overcome the 260 char path limit on Windows
git config --system core.longpaths true

or alternately

git config --global core.longpaths true


git config --global alias.ci commit
git config --global alias.st "status --short"
git config --global alias.stat status
git config --global alias.co checkout
git config --global alias.up pull
git config --global alias.unstage "reset HEAD"
git config --global alias.undo "reset --hard HEAD"
git config --global alias.ls "ls-files --eol"
git config --global alias.ls-log "log --name-only --decorate"
git config --global alias.l "log   --oneline --graph  --decorate"

# if you install git-flow
git config --global alias.release "flow release"
git config --global alias.hotfix  "flow hotfix"
git config --global alias.feature "flow feature"
git config --global alias.bugfix "flow bugfix"


git config --global modifies $HOME/.gitconfig

git config --system modifies the systemwide /etc/gitconfig

git config --file <filename> creates/modifies the named config file


Adding an existing repo as a module in your project

  • In your local cloned git project dir, type:
git submodule add <repourl>
  • This will create a new file .gitmodules along with the base dir
  • Add as many submodules as you need
  • When done, run:
git commit -a -m "added submodules"

Cloning a repo with submodules

git clone --recursive <main-git-project-url>

Fetching submodules in an existing git repo

  • If other committers add new modules, or if you clone a project with modules without --recursive, run
git pull  # pull in latest changes
git submodule init 
git submodule update

Updating specific submodules

  • By default, all submodules are updated using git submodule update
  • To update a specific submodules to the latest master branch present on the server
git submodule update --remote <submodulename>
  • alternately,
cd <submodule>
git fetch 
git merge origin/master

Updating submodules to a different branch

  • If you need to update submodules to a branch other than master, to say for example, develop modify the .gitmodules file using
git config -f .gitmodules submodule.<modulename>.branch develop
  • Subsequent git submodule update --remote will update the submodule to the develop branch

Diffing with submodules

  • From the main project, run:
git diff --submodule
  • To set --submodule as default for diff:
git config diff.submodule log

Pushing submodule updates

  • git push in the submodule tree.
  • If there are too many submodules, check which submodules have require a push using
git push --recurse-submodules=check
  • Push all modified submodules using
 git push --recurse-submodules=on-demand

foreach subcommand

  • git submodules have a convenient foreach command if you need to work with all submodules
  • Example 1: stash all submodules: git submodule foreach 'git stash'
  • Example 2: Diff all submodule dirs: git submodule foreach 'git diff'

Prep release

  • Make an annotated tag if not using git flow release (git tag --annotate ...)
  • Verify using:
    git describe master
  • Make a release tarball
git archive tagname --prefix projdir/ | gzip -c > $(git describe master).tar.gz    
  • To make a release zip:
git archive tagname --prefix projdir/ --format zip -o $(git describe master).zip    


Rebase usage

  • git rebase --onto newbase branch_x topicbranch
  • git rebase will automatically checkout topicbranch first
  • rebase will apply commits from the common ancestor of branch_x and topic_branch to the newbase.
  • Commits unique to branch_x are not merged to newbase.
  • Eg: git rebase --onto master feature-1 feature-2 will checkout feature-2, find the ancestor of feature-1 and feature-2, apply all patches from the ancestor commit upto feature-2's latest commit to the master branch. The master branch can be fast forwarded to feature-2 using: git checkout master; git merge feature-2
  • git rebase basebranch topicbranch
    • git rebase will automatically checkout topicbranch first
    • Then patches to their common ancestor are applied to basebranch
    • Eg: git rebase master feature-1 will apply all patches from the ancestor commit upto feature-1's latest commit to the master branch. The master branch can be fast forwarded to feature-1 using: git checkout master; git merge feature-1

Note: After fast-fwding, the feature branches can be deleted.

Rebasing from the same branch

  • If you and another user work on the same branch, and the other user pushes changes, then you must pull before you push, effectively creating a merge. A safe way without cluttering up the log is:
git pull --rebase
  • This makes git pull the changes, and then re-apply(rebase) your unpushed commits on top of the latest version of the remote branch, removing the need for the merge.

Merge remote changes on local master

  • git fetch origin; git merge origin/master

Merge local branch as well as remote master on local master

git fetch origin
git log --no-merges localbranch..origin/master
git checkout master
git merge localbranch
git merge origin/master
git push origin/master
# Set default behvavior
* text=auto

# Windows batch files
*.bat text eol=crlf
*.cmd text eol=crlf

# Binaries
*.jar    binary
*.zip    binary
*.png    binary
*.gif    binary
*.jpg    binary
*.jpeg   binary
*.xz     binary
*.zst    binary
*.gz     binary
*.bz2    binary