Skip to content

Git Commands#

Git Config#

  • Git Config Best Practice
  • Show Options

    Bash
    git config --list --show-origin # all variables with origin i.e. file, standard input, blob, command line
    git config --list --show-scope  # all variables with scope i.e. worktree, local, global, system, command
    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

    INI
    # Submodule settings
    [alias]
      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
    [diff]
      submodule = log # clearer container diffs when referenced submodule commits changed
    [status]
      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
Bash
git clone --config core.autocrlf=false https://github.com/batiati/mustache-zig
  • Re-normalize line-endings
Bash
git add --renormalize .
git status
git commit -m "Introduce end-of-line normalization"
Bash
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
Bash
# 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
Bash
# 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
Bash
# 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
Bash
# 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
Bash
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

Bash
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
Bash
# 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
Bash
# Diff staged changes vs working directory
git difftool --dir-diff
# Diff staged changes vs HEAD
git difftool --dir-diff --staged

Git Commit History Manipulation#

Bash
git reset --soft 'HEAD^'
  • Force clean local repository (including deleting unchecked in files) (Reference)
Bash
git clean -d -x -f
  • Create patch containing all commits in current but not in the master branch (Reference)
Bash
git format-patch origin/master --stdout > mypatch.patch
  • GitExtensions: filter a set of branches
Bash
Bebylon* --remotes=upstream/release* --remotes=upstream/dev*
Bash
git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new
Bash
# 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)](http://www.gitguys.com/topics/whats-the-deal-with-the-git-index)
git reset --soft HEAD~1
  • Remove all untracked files and directories. (-f is force, -d is remove directories)
Bash
git clean -fd
Bash
git clean -fdx
Bash
git rebase -i HEAD~2
# Then select squash for the second commit
  • To move folders into a different folders in git (Reference)
Bash
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)
Bash
# 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.

Git-P4#

TLDR#

  • 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: https://stackoverflow.com/questions/931882/how-to-apply-a-git-patch-from-one-repository-to-another

    Bash
    $ 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
    INI
    [git-p4]
    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'"

Using#

  • Set P4 Vars:

    Bash
    set P4PORT=public.perforce.com:1666
    set P4USER=yourusername
    set P4PASSWD=yourpassword
    

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

  • Submit: git p4 submit

More Info#