Branching
Each branch was deviated from certain commit of another branch, and could have its own HEAD
when actual divergence was applied. So a branch besides the main branch is essentially a sequence of commits starting with a divergence from another branch.
IMPORTANT
Branch is a concept upon commits, the branch is sometimes equivalent to the latest commit of that branch. A branch is just a special commit points to latest commit of that branch and can trace back to the divergence.
Branch Identifier
- branch name: generally refers to local branch
<remote>/<branch>
: refers to remote branch copy fetched in local@{upstream}
or@{u}
: see Remote Branch Identifier
NOTE
Given the context that upstream is of a branch, git rev-parse @{u}
should return the fetched latest commit hash of remote in local.
Branch Inspection
A branch has its dedicated text file containing its latest commit hash at ./.git/refs/heads/<branch>
$ cat ./.git/refs/heads/msbuid_ls
4bfbc0c67e39f5615e0cdc4535611af1e71040d8
2
If the latest commit hash is the only thing the branch knows, how could it collect all of the commits when git requires to? The fact is, commits are chained with their parent and child, so git can track back along to the point where the branch was diverged.
Branch Manipulation
NOTE
See git help branch
and tldr git-branch
. Or git help switch
and tldr git-switch
.
-d|--delete
: delete branch-m|--move
: rename branch-c|--copy
: copy branch...
IMPORTANT
Manipulating branches doesn't mean the commits of branches would be manipulated or deleted, they're mostly attached/detached or we can say, they live in the wild waiting to be tracked by a branch.
Merging & Rebasing
- General merge: merges one branch history to another
- this generates a merge commit, containing the information about all parents that were merged together, the merge commit is added to the branch merged into.
- Fast forward merging: when there' no actual divergence on graph between the parent branch and child branch, git can simply move the head pointer of current branch directly from the merge-base to the top commit of the branch to be merged from
- generates no merge commit by default, but if do want to keep the history, use
git merge --no-ff
even when the history could be linear.
- generates no merge commit by default, but if do want to keep the history, use
- Rebasing: move the divergence point(aka the base) to another commit.
- generates no merge commit
- alters your local commit history since its entire root of divergence has been changed.
- DO NOT use
rebase
in public branch, use it only on your local branch.- If you're sure there's only you to work with the public branch(and its sub branches), feel free to
git push --force
to override the history on remote.
- If you're sure there's only you to work with the public branch(and its sub branches), feel free to
IMPORTANT
Always merge on public branches, rebase on local branches.
Merge
A merging involves two branches, the subject of the operation is the branch to merge to. A merge operation creates a merge commit on the subject branch.
- checkout to the branch to merge to.
git merge <another_branch>
- use
--no-ff
to always generate a merge commit.
- use
Rebasing
Differ from merge
subcommand, rebase
is the change on the branch itself, only one branch is involved in the whole operation.
- checkout to the branch you need to alter its merge-base
git rebase <commit_identifier>