Git, everyday commands and internal

 Git

  • Everyday commands and workflow
  • Git internal

Everyday commands and workflow

I usually keep a file called command in the parent directory to remind me of things I don't want to remember

content_copy
git checkout -b feature/new_branch # create new branch feature/new_branch from current branch
git commit -m 'message' # new snapshot
git commit --amend # append current change to previous snapshot
git pull --rebase origin develop # merge develop branch changes to local but put your changes on top
git push # sync local changes to remote
git push -f # force sync local changes to remote
git reset HEAD~ # undo last commit
git merge --continue # after solve conflict
git merge --abort # abort merging

git stash apply
git checkout stash -- .  # force stash apply

Do the setup once, hopefully only once

content_copy
git config --global credential.helper store
git config --global user.name "Your Name"
git config --global user.email "you@email"

just use UI for the following commands

content_copy
git add
git diff
git stash # store latest change

Internals

Git is essentially DAG

Object Types

  • Commit - A snapshot of the working tree - Author message, a pointer to a tree of changes
  • Tree - Directory listing - Pointer(s) to file names, content, other trees
  • Blob - Contents of a File - Data (source code, pictures, videos, etc.)

Each object file has a 40-char SHA1 hash as its filename (the first 2 char is to shard directories)

  • display object content git cat-file -p <SHA>
  • display object type git cat-file -t <SHA>

Branches are named pointers to commits
HEAD is a special pointer to the latest commit on the current branch

Demo

Empty git repository

content_copy
.git/
├── HEAD # current HEAD
├── branches
├── config # origin, fetch location
├── description # description
├── hooks # example hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── info
│   └── exclude # local exclude, not share with other
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

Then let's do a commit

content_copy
.git
├── COMMIT_EDITMSG # temporary file stores git commit message
├── HEAD
├── branches
├── config
├── description
├── index # a binary file containing a sorted list of path names, each with permissions and the SHA1 of a blob object, can view using git ls-file
├── info
│   └── exclude
├── logs
│   ├── HEAD # (cat .git/logs/HEAD) history of commit, 0000000000000000000000000000000000000000 db2cfba18e32002b54fe3af54e799020bae23aa4 Your Name <you@email> 1611743087 +1100       commit (initial): hello.txt
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 4b
│   │   └── 825dc642cb6eb9a060e54bf8d69288fbee4904 # dangling tree (no used)
│   ├── 96
│   │   └── 632ab0bf6c8a003b8e09bd4ebd8e5f5eac141b # tree that points to blob
│   ├── db
│   │   └── 2cfba18e32002b54fe3af54e799020bae23aa4 # commit
│   ├── e6
│   │   └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391 # blob
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

Hooks

Git hooks are scripts that run automatically every time a particular event occurs in a Git repository

we can set up a pre-commit hook that checks semantic commit before each commit (similarly linting and static analysis):

./commit-msg

content_copy
#!/bin/sh
#
# hook script to check the commit message format
# example format type(scope): subject

test "0" != "$(cat $1 | 
	egrep '^(build|ci|docs|refactor|style|test|feat|fix|perf|param)\((.+)\)\: .+' | 
	wc -l)" || {
	echo >&2 "ERROR: Please follow commit message format \"type(scope): subject\"";
	echo ""
	echo "DESCRIPTION"
	echo "- type"
	echo "	prefix represent kind of the change"
	echo "	available types: build|ci|docs|refactor|style|test|feat|fix|perf|param"
	echo "	- build"
	echo "		build system, package dependencies"
	echo "	- ci"
	echo "		continuous integration and deployment system"
	echo "	- docs"
	echo "		documents"
	echo "	- refactor"
	echo "		code refactor"
	echo "	- style"
	echo "		code style change"
	echo "	- test"
	echo "		refactor existing test, new test (unit, integration)"
	echo "	- feat"
	echo "		new function"
	echo "	- fix"
	echo "		bug fix"
	echo "	- perf"
	echo "		performance improvement"
	echo "	- param"
	echo "		pipeline parameter"
	echo "- scope"
	echo "	information represent context of the change"
	echo "	this can be package name, script name"
	echo "- subject"
	echo "	concise description of the actual change"

	exit 1
}
content_copy

Comments