Git cheat sheet

Git commands that are not intuitively found:

  • Removing a subtree from a repository including all of its history (e.g. when non-open-source files were committed to a repository before pushing the repo to an external server or to remove old directories after splitting a repo):
    git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch <DIRECTORY TO REMOVE>" --prune-empty HEAD
  • Removing everything besides a specific directory (from
    git clone --no-hardlinks XYZ ABC
    cd ABC
    git filter-branch --subdirectory-filter ABC -- --all
    git reset --hard
    # and now really, really clean up all objects not referenced anymore...
    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    git repack -ad
    git clean -d -f
    git gc --aggressive
    git prune
    # instead of the above, the following might reclaim more space, a lot quicker:
    cd ..; mkdir ABC-min.git; cd ABC-min.git
    git init --bare
    cd ../ABC
    git push ../ABC-min.git HEAD
  • Removing everything besides a list of files and directories and tracking their history even through renames and copies, which the above method doesn't track (from
    git clone --no-hardlinks XYZ ABC
    cd ABC-d"\\n" git rm --cached -r' -- --all
    git filter-branch --prune-empty --index-filter 'git ls-tree -r --name-only --full-tree $GIT_COMMIT \
        | grep -iv "filename1" | grep -iv "filename2" | grep -iv "directory-regex1" | grep -iv "directory-regex2" | ... \
        | grep -v "^git-changelog" | xargs -r -d"\\n" git rm --cached -r' -- --all
    # same as above with git push/pull to reclaim space
  • Merging a previously separate (typically small) repository (let's call it rep1) into an existing (typically larger) repository (let's call it rep2) under a new path (let's call it rep1path), keeping history
    cd rep1
    mkdir -p rep1path
    git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} rep1path 
    git commit -m "Move to new path in preparation of merge into rep2"
    [git push] - optional if not working with local repos but going through remote
    cd rep2
    git remote add oldrep1 URL-to-rep1
    git fetch oldrep1
    git merge oldrep1/master
    git remote remove oldrep1
  • Importing from subversion (from
    mkdir newgitrep
    cd newgitrep
    git svn init URL-to-svn-rep --stdlayout --prefix=svn/ [this will prefix the branch names with svn/ to make it clear that they were imported]
    git svn fetch [this will take some time]
    for branch in `git branch -r | grep "svn/" | grep -v "svn/tags" | sed 's/ branches\///'`; do
      git branch $branch refs/remotes/$branch
    for tag in `git branch -r | grep "tags/" | sed 's/ tags\///'`; do
      git tag -a -m"Converting SVN tags" $tag refs/remotes/$tag
    git remote add oriting new-remote-git-repo-URL
    git push --all origin
    git push --tags origin


This page was last modified on 2015-03-15