Branching - seljukgulcan/git-notes GitHub Wiki
Branching is killer feature of git.
Git encourages workflows that branch and merge often.
Branch is a movable pointer to commit. HEAD is a pointer to current branch.
git branch
Lists branches
git branch <branch>
Create a new branch but does not make it HEAD.
git checkout <branch>
Changes current branch and working directory according to that branch
git merge <branch>
Merges current branch into target branch.
git branch -d <branch>
Deletes target branch.
If a commit is just a head of another one. Merging operation is done by fast-forwarding. That is, git just changes the location of branch pointer. However, if there is a divergent changes, git try to merge two branch by three-way merge using branch commits and common ancestor commit.
git branch -v
lists branches with their last commit.
git branch [--merged|--no-merged]
Shows branches (not)merged with current branch.
Not merged branches cannot be deleted with git branch -d <branch>
. -D
can be used to force.
Chapter 3.4 talks about different branching workflows (Long-term vs short-term). For git, it does not change anything.
Remote tracking branches are completely separate branches. They are in (remote)/(branch) form. Only difference is that they are not moving pointers. They only move when local communicates with remote.
When we git fetch <remote>
, It fetches information on but it fetches this data into remote-tracking branches (remote)/(branch). Therefore, if we do some commits on local and someone else do commits on remote, git log looks like this when we fetch remote:
git push <remote> <branch>
git push <remote> <local_branch>:<remote_branch>
Push <local_branch> to <remote_branch>
When we fetch data from a remote using git fetch <remote>
, we get all remote branches but this does not create local branches according to them. Users should create those branches themselves.
git checkout -b <local_branch> <remote>/<branch>
This creates a tracking local branch tracking remote.
Related to tracking branch and upstream branch definitions:
Checking out a local branch from a remote-tracking branch automatically creates what is called a “tracking branch” (and the branch it tracks is called an “upstream branch”). Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git pull, Git automatically knows which server to fetch from and branch to merge into.
git checkout --track origin/serverfix
turns current branch into tracking branch which track origin's serverfix branch.
When we do git checkout <branch>
, if local branch named does not exist and exists in only one remote, git creates tracking branch automatically.
git branch -vv
This will list out your local branches with more information including what each branch is tracking and if your local branch is ahead, behind or both.
Of course this command shows information according to last communication with remote server.
git fetch --all
Fetches all remotes so remote tracking branches are synced with remotes.
git push [remote] --delete [branch]
deletes branch on remote.
git pull = git fetch + git merge
Instead of merging one branch to another, we can reapply changes in one branch to another branch to create a linear history log. To create a linear and clean history is the purpose of rebasing. End products of merging and rebasing are the same.
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command`
(Changes base of experiment branch so that master becomes its base (parent commit) and divergent changes in experiment reapplied on working directory at master's position and experiment branch now points to this snapshot.)
We can do more extreme rebases. Such an example is here
First let’s assume your topic is based on branch next. For example, a feature developed in topic depends on some functionality which is found in next.
o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topic
We want to make topic forked from branch master; for example, because the functionality on which topic depends was merged into the more stable master branch. We want our tree to look like this:
o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o next
We can get this using the following command:
git rebase --onto master next topic
The only rule of rebasing is :
Do not rebase commits that exist outside your repository.