Skip to main content
Git

Git #

References:

Basic terms:

  • tree: folder
  • blob: file
  • HEAD: the current state of the files that you’re looking at
  • stage: telling git about changes
  • commit: record the staged changes

Config #

Set editor #

Ref: How can I set up an editor to work with Git on Windows? - Stack Overflow

Set a different editor than $EDITOR:

git config  --global core.editor vim

Useful Aliases #

Oh-My-Zsh Git Plugin #

References:

# git status
gst

# git pull
gl

# git push
gp

# git checkout master/main
gcm

# git commit -m
gcmsg "message here"

# All cached changes
# git diff --cached
# git diff --staged
gds

# git diff --word-diff
gdw

# git log --oneline --decorate --graph
glog

# git remote --verbose
grv

Change git CLI language #

Does not work in tmux for reasons unknown.

In ~/.zshrc:

# Use languages other than default shell language
alias git='LANG="zh_CN.UTF-8" git'

Observe Things #

Logs #

See all files changed with each commit: (credit)

git log --stat

One-line graphic log: (credits: new, old); (tformat is preferred over format, see credit)

git log --all --decorate --oneline --graph

# old version:
git log --graph --full-history --all --date=short --pretty=tformat:'%Cred%h%Creset %C(bold green)%ad%Creset %s %C(yellow)%d%Creset %Cblue<%an>%Creset'

Diff #

Difference between most recent commit and second most recent commit: (credit)

git diff HEAD^ HEAD

Difference between branches: (credit)

git diff branch_1..branch_2

Difference between staged (added) changes and most recent commit:

git diff --staged

Only list changed file names and status:

Meaning of the marks

Git - git-diff Documentation

  • A: Added
  • C: Copied
  • D: Deleted
  • M: Modified
  • R: Renamed
  • T: Type (i.e. regular file, symlink, submodule, …) changed
  • U: Unmerged
  • X: Unknown
  • B: Broken pairing
# Newest commit
git diff --name-status HEAD~1..HEAD

# Compare the current state and some previous commit
git diff --name-status <commit>

# Compare two previous commits
git diff --name-status <new-commit>..<old-commit>

Files #

Show all files under git version control:

# r for recursive
git ls-tree -r --full-tree --name-only HEAD
# or
git ls-files

Find out how many files are being tracked: (credit)

# All files
git ls-files | wc -l

# Some kind of file (e.g. Markdown)
git ls-files | grep "\.md$" | wc -l

Blame #

Reference: Git - git-blame Documentation

# Inspect lines 20~30
git blame a-file.md -L 20,30

# Inspect from start of file to line 30
git blame a-file.md -L ,30

# Inspect from line 20 to end of file
git blame a-file.md -L 20,

Remote #

Show all remote URLs:

git remote --verbose
git remote -v

Commit-Level Operations #

Interactive chunk-staging:

git add --patch somefile.txt
git add -p somefile.txt

Change last commit message:

git commit --amend

Gently squash last two (or any number of) commits: (credit)

git reset --soft HEAD~2
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"

Undo last commit: (credit)

git reset HEAD~1

Apply Late .gitignore #

Commit first:

git commit -m "add/change .gitignore"
subl .gitignore

Add something to .gitignore, for example:

# Things to ignore
**/.DS_Store
**/*.pdf

# Things to keep
!roadmap.pdf

Apply changes:

git rm -r --cached . && git add . && git commit -m "apply .gitignore"

git bisect #

TBA

Repository-Level Operations #

Change file extension #

Ref: Changing file extensions in bulk using Git Bash | Samantha Miller

This command works recursively.

find . -name '*.pug' -exec sh -c 'git mv "$0" "${0%.pug}.html"' {} \;

Branches #

See all branches:

git branch

# See some more info
git branch --verbose
git branch -v

Create branch:

git branch my-new-branch
git checkout my-new-branch

# or
git checkout -b my-new-branch

Change branch name:

git branch -m master main
git push -u origin main

# external action required: go to origin (e.g. GitHub)
# and change the default branch

git push origin --delete master

Move files changes to another branch: (credit)

# p for patch
git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p

Merge master to new branch: (credit)

git pull origin master

Delete local branch:

git checkout master
git branch -d my-old-branch

Delete all gone local branches: (credit)

git remote prune origin

Delete remote branch:

git push -d origin my-old-branch

Merge Master into Branch #

Credit: GitHub

# From your project repository, bring in the changes and test.
git fetch origin
git checkout -b "my-branch" "origin/my-branch"
git merge "master"

# Merge the changes and update on remote.
git checkout "master"
git merge --no-ff "my-branch"
git push origin "master"

Remove sensitive data from history #

Haven’t tried: Removing sensitive data from a repository - GitHub Docs

Split Repo #

Credit: git subtree - Detach (move) subdirectory into separate Git repository - Stack Overflow

# Prepare the old repo
cd <big-repo>
git subtree split -P <name-of-folder> -b <name-of-new-branch>

# Create new repo
mkdir ~/<new-repo> && cd ~/<new-repo>
git init
git pull </path/to/big-repo> <name-of-new-branch>

# Clean old repo
cd <big-repo>
git rm -rf <name-of-folder>

Submodule #

Add #

Credit 1, 2

# Default branch
git submodule add <remote-URL>

# Specify branch
git submodule add -b <branch-name> <remote-URL> <preferred-folder-name>

# Track a specific branch after init
git submodule set-branch --branch <branch-name> <folder-name>

Initial pull submodule:

git submodule update --init --recursive

Update (Fetch) #

Update all submodules: (credit)

git submodule update --remote

Show list of all submodules: (credit)

# Either will work
git ls-tree -r HEAD
git submodule status

Edit #

Make changes to submodules (in .gitmodules), then do git submodule update --init --recursive --remote (credit)

[submodule "something"]
    path = something
    url = https://github.com/something/something.git
    ignore = untracked
    branch = new-branch

Change the directory name for a submodule: (credit)

  1. Update .gitmodules.
  2. Run git add .gitmodules
  3. Run git mv /path/to/old/directory /path/to/new/directory
  4. Run git add .

Change remote URL for a submodule: (credit)

git submodule set-url <path> <newurl>

Remove #

The easy way: git rm <path-to-submodule>

The hard way: (credit)

  1. Delete the relevant section from the .gitmodules file.
  2. git add .gitmodules
  3. Delete the relevant section from .git/config.
  4. git rm --cached <path-to-submodule>
  5. rm -rf .git/modules/<path-to-submodule>
  6. rm -rf <path-to-submodule>

Pre-Commit #

TBA…

Git Flow #

References:

Installation:

brew install git-flow-avh

Initialise: (-d means using default branch names)

git flow init -d

Write new feature:

# Before beginning
git flow feature start my-new-feature

# After final commit
git flow feature finish my-new-feature

Debugging #

UTF-8 character in filename are displayed in numbers #

git config --global core.quotepath false