Chapter 6
Branches
There are two important reasons why version histories do not always run linear, commit by commit:
In both cases, branches are created in the commit history graph.
Parallel Development
When more than one developer works on the same piece of software with Git, branches are created in the commit graph. The upper half of Figure 6.1 shows how two independent developers have created succeeding versions (commits C and D) to commit B in their local repositories. Below it you see the repository after a merge (see Chapter 9 on how to do this). It has created a branch. This type of branching can hardly be avoided in parallel development.
Figure 6.1: Parallel development
Bug Fixes in An Older Version
A branch may get created due to parallel development. In addition, a branch may also get created when fixing bugs in an older software version. Figure 6.2 shows an example: While the developers are working intensively on the version for the upcoming release (commits C and D), an error in the current software version (commit B) is detected. Since the new features in commits C and D are not ready yet for delivery, a bug fix E is created based on commit B.
Figure 6.2: Bug fixes in an older version
Branches
In the example in Figure 6.3 you can see on the one hand a release1 branch for the current release version and the master branch for current development. With each new commit, an active branch wanders. The right panel shows how the release1 branch wanders further with the bug fix.
Figure 6.3: Branches in the version graph
Swim Lanes
Branches can be thought of as parallel lines of development. You can visualize this as swim lanes in the commit graph (See Figure 6.4).
Figure 6.4: Branches as parallel lines of development
Note: Git does not know if a commit is assigned to a branch; the division into lanes is an interpretation that to some extent is arbitrary.
The Active Branch
In a Git repository there is always exactly one active branch. The branch command (without options) shows a list of all branches. The active branch is highlighted with an asterisk (*).
> git branch a-branch * master still-a-branch
The active branch will always continue with any new commit, pointing to the most recent commit. You can use the checkout command to change the active branch.
> git checkout a-branch
Step by Step
Creating a branch
A new branch will be created.
1a. Branching off the current commit
> git branch a-branch
1b. Branching off any arbitrary commit
You can also branch off any arbitrary commit. To do this, you must specify the start commit for the new branch.
> git branch still-a-branch 38b7da45e
1c. Branching from an existing branch
> git branch still-a-branch older-branch
2. Switching to the new branch
The branch command only creates a new branch, but does not switch you to the new branch. To switch to the new branch, use the checkout command.
> git checkout a-branch
Shortcut: Creating a branch and switch to it
> git checkout -b a-branch
Step by Step
Checkout denied. What now?
Normally you can use the checkout command to bounce back and forth between branches. However, if there are changes in the workspace, you have to decide how to get around these local changes.
1. Checkout
Here is how a checkout may be denied.
> git checkout a-branch
error: Your local changes to the following files would be overwritten by checkout: foo.txt Please, commit your changes or stash them before you can switch branches. Aborting
There are changes in the workspace or the staging area, which were still not confirmed with a commit. You have to decide what to do with the changes.
2a. Commit and switch
> git commit --all > git checkout a-branch
2b. Discard the changes and switch
You can force a switch with the --force option. However, all local changes will be overwritten!
> git checkout --force a-branch
2c. Stash and switch
You can stash the changes using the stash command (See the section “Stashing” in Chapter 4) and then switch. Later you can retrieve them with the stash pop command.
> git stash > git checkout a-branch
Resetting A Branch Pointer
The branch pointer to the active branch moves farther with each commit. Therefore, it is rarely necessary to set the branch pointer directly. However, sometimes you lose track of what is happening and would like to return to a previous state. In this case, you can reset the branch pointer with the reset command.
> git reset --hard 39ea21a
Here the pointer is set to the active branch of commit 39ea21a. The --hard option ensures that the workspace and staging area are also set to the state of commit 39ea21a.
Be warned that reset --hard overwrites any changes in the workspace and staging area. You should stash the changes with git stash before resetting.
Deleting A Branch
Step by Step
Deleting a branch
You can delete a branch with branch -d.
a. Deleting a terminated branch
> git branch -d b-branch
b. Deleting an open branch
If the branch you are trying to delete is not yet transferred to a different branch, such as the master, Git will give you a warning and refuse to delete it. If you want to delete the branch anyway, use the -D option.
error: The branch 'b-branch' is not fully merged. If you are sure you want to delete it, run 'git branch -D b-branch'.
> git brach -D b-branch Deleted branch b-branch (was 742dcf6).
Step by StepRestoring a deleted branch
Git manages branches so that when you delete a branch, Git only deletes the pointer to the commit. The commit objects are still in the repository. You can restore a deleted branch if you know the commit hash in the message you get after deleting a branch.
a. Restoring a branch (commit hash known)
> git branch a-branch 742dcf6
b.1. Determining the commit hash
If you do not know the commit hash of the branch you want to restore, you can find it using the reflog command.
> git reflog
d765a1e HEAD@{0}: checkout: moving from b-branch to master 88117f6 HEAD@{1}: merge b-branch: Fast-forward 9332b08 HEAD@{2}: checkout: moving from a-branch to b-branch 441cdef HEAD@{3}: commit: Expanded important stuff
b.2. Restoring the branch (with hash from reflog)
> git branch b-branch HEAD@{1}
Getting Rid of the Commit Objects
The gc command (gc for garbage collect) cleans up the repository and removes commit objects that are not reachable from the current branches. If you really want to make sure your repository is clean, then clone it and delete the original.
Summary
3.137.41.205