Skip to content

Git Commands#

Git Config#

  • Git Config Best Practice
  • Show Options

    git config --list --show-origin # all with origin
    git config --list --system      # system-wide variables i.e. from git installation folder
    git config --list --global      # global variables i.e. from ~/.gitconfig
    git config --list --local       # repository variables i.e. from .git/config

  • Diff tool config

    # Submodule settings
      ssync = git submodule sync --recursive && git submodule update --init --recursive
      spull = !git pull && git submodule sync --recursive && git submodule update --init --recursive
      spush = push --recurse-submodules=on-demand
      submodule = log # clearer container diffs when referenced submodule commits changed
      submoduleSummary = true # git status is useful again when a referenced submodule commit changed
    # Diff tool settings
    [difftool "araxis"]
      path = 'C:/Program Files/Araxis/Araxis Merge/compare.exe'
    [mergetool "araxis"]
      path = 'C:/Program Files/Araxis/Araxis Merge/Compare.exe'
      cmd  = \C:/Program Files/Araxis/Araxis Merge/Compare.exe\ '$REMOTE' '$BASE' '$LOCAL' '$MERGED'
    [difftool "beyondcompare"]
      path = 'C:/Program Files/Beyond Compare 4/bcomp.exe'
      cmd  = 'C:/Program Files/Beyond Compare 4/bcomp.exe' '$LOCAL' '$REMOTE'
    [mergetool "beyondcompare"]
      path = 'C:/Program Files/Beyond Compare 4/bcomp.exe'
      cmd  = 'C:/Program Files/Beyond Compare 4/bcomp.exe' '$LOCAL' '$REMOTE' '$BASE' '$MERGED'

Git Fetch/Clone#

  • Clone with specific line-endings
git clone --config core.autocrlf=false
git clone url --single-branch
# shallow clone only the remote primary
git clone url --single-branch
# shallow clone up to depth
git clone url --depth 1 #implies --single-branch
# shallow clone up to date
git fetch --prune origin --verbose --shallow-since=2022-02-26
  • Unshallow
# unshallow the current branch
git fetch --unshallow

# unshallow all the branches
git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch --unshallow

Git Submodule#

  • initialize repo with submodule
# init repo with submodules
git submodule update --init --recursive

# sync repo with submodules
git submodule sync --recursive && git submodule update --init --recursive

# shallow clone with submodules up to depth
git clone --depth 1 [repo_url]
git submodule init
git submodule update --depth 1
  • add new submodule
# add new submodule with tracking branch
git submodule add -b [branch_name] [repo_url] [path/to/submod]
git submodule update --remote

# add shallow submodule
git submodule add --depth 1 [repo_url] [path/to/submod]
git config -f .gitmodules submodule.[path/to/submod].shallow true
git config -f .gitmodules submodule.[path/to/submod].branch [branch_name]
  • modify existing submodule
# change existing submodule tracking branch
git submodule set-branch -b [branch_name] -- [path/to/submod]

# move submodule
git mv [old/path/to/submod] [new/path/to/submod]
  • remove submodule
git rm [path/to/submod] && git commit
  • [!info] can be undone with git revert submodule's .git directory (e.g. .git/modules/[path/to/submod]) is not removed to make possible past commit checkout without requiring fetching from another repository (Reference)

  • remove submodules completely

git submodule deinit -f [path/to/submod] # remove the submodule entry from .git/config
rm -rf .git/modules/[path/to/submod]     # remove the submodule directory from the superproject's .git/modules directory
git rm -f [path/to/submod]               # remove the entry in .gitmodules and submodule directory located at [path/to/submod]

Git Diffing#

  • Diff working tree
# Diff working tree vs commit; Use '--' for working tree e.g.
git difftool --dir-diff HEAD --

# Diff across branches
git difftool 4.17..bebylon -- /d/UnrealEngine/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp
git difftool --dir-diff release ~HEAD

# Diff folders between history or two different commits
git difftool --dir-diff 27990a4451cf9458b280c9be027af41898721791~1 27990a4451cf9458b280c9be027af41898721791
  • Diff staged changes
# Diff staged changes vs working directory
git difftool --dir-diff
# Diff staged changes vs HEAD
git difftool --dir-diff --staged

Git Commit History Manipulation#

  • Undo last commit (Reference): git reset --soft 'HEAD^'

  • Force clean local repository (including deleting unchecked in files) (Reference): git clean -d -x -f

  • Create patch containing all commits in current but not in the master branch (Reference)

git format-patch origin/master --stdout > mypatch.patch
  • GitExtensions: filter a set of branches
Bebylon* --remotes=upstream/release* --remotes=upstream/dev*
git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new
# You want to nuke commit C and never see it again
git reset --hard HEAD~1
# Undo your commit but leave your files and your index ([Reference](
git reset --soft HEAD~1
  • Remove all untracked files and directories. (-f is force, -d is remove directories)
git clean -fd
git clean -fdx
  • Squash/Merge previous two commits (Reference)
git rebase -i HEAD~2
# Then select squash for the second commit
  • To move folders into a different folders in git (Reference)
git filter-branch --tree-filter 'mkdir -p /path/to/tmp; mv * /path/to/tmp; mkdir subdir; mv /path/to/tmp/* subdir/' --tag-name-filter cat --prune-empty -- --all
  • Rebase against another branch overriding conflicts with your own branch changes (Reference)
# assuming branch-a is our current version
#   ours:   branch-b
#   theirs: branch-a
git rebase -Xtheirs branch-b

[!danger] -Xtheirs and -Xours are counterintuitive For rebase: -Xtheirs refers to your local current branch that you want to replay ontop of the master branch. For merge: -Xours refers to the local branch.



  • you need to use python 2.7
  • you can use this to sync from perforce to a git and back (it's brittle)
  • when doing git clone, you have to specify to use client spec git p4 clone //depot/main/BBR/Source . --use-client-spec
  • can also exclude paths and have multiple depot paths
  • with different directory structures, you can reformat patch files:

    $ cat patch_file | git am   \
            -p1                 \ # remove 1 leading directory ('static/')
            --directory='lib/'    # prepend 'lib/'

  • you can also cherry pick commits directly (git will automatically resolve the different path )

  • remember to have your git-p4 repo in a separate directory from your actual p4 directory
  • you can merge unrelated git histories with git merge myotherbranch --allow-unrelated-histories
  • use these git config -e settings
    skipSubmitEdit = true
    useclientspec = true

Install instructions#

  • Needs python 2.7
  • git config --global alias.p4 !"python 'C:/Program Files (x86)/Git/mingw32/libexec/git-core/git-p4'"


  • Set P4 Vars:

    set P4USER=yourusername
    set P4PASSWD=yourpassword

  • Clone repo: git p4 clone --detect-branches //depot/perforce_software/p4jenkins

  • Submit: git p4 submit

More Info#

Last update: 2022-11-15