Working with Git branches
Command Line – Git Branches
Git makes version control as simple as possible. To manage your Git branches successfully, you need to learn the ins and outs of git branch and git merge.
In a previous issue of Linux Magazine [1], I outlined how to set up a Git Repository (Table 1). Once a repo is set up, you are ready to use Git [2] for version control.
Table 1
Basic Commands for Creating a Repository
git clone URL |
Copy remote repository to your local hard drive. |
git pull URL |
Sync a local repository with the remote original. |
git init |
Create a local repository in the current directory. |
git add FILE1 FILE2 |
Stage (prepare) files in the repository. |
git commit -m "MESSAGE" |
Add staged files to the repository. |
Note: Each of these commands has other options, as well as its own man page. These are only the basic commands. |
---|
Version control in Git is about managing and creating branches (collections of files that are variations of each other). By making a branch, you can edit files without altering the original. Later, if you choose, you can merge branches to create a more advanced copy.
The process of managing branches is so simple that branches tend to proliferate in projects that use Git, with branches being created for different users, subsystems or hardware architectures, each release, experiments, or any other criteria that may useful. In fact, while other version control systems also use branches, using Git repos is so flexible that it is widely considered Git's defining feature. Two Git sub-commands are the main tools for managing branches: git branch
[3], which sets up and edits branches, and git merge
[4], which combines branches.
A Basic Overview
When a repository is created, a default called master
is created. It is the top-level branch, analogous to the root directory on a filesystem, with its commits the equivalent of the root directory's files. Otherwise, master
is no different from any other branch. However, ordinarily, the commits in master
are not edited – the whole point, after all, is to have a clean set of files in case a recovery is needed. The most common workflow is to create a branch below master
and edit the files there.
Git manages the branch tree with a series of pointers. The current branch is kept track of with a pointer called HEAD
. You create a new branch locally with the command:
git branch NAME
If you want to move to the new branch immediately after creating it, instead use
git checkout -b NAME
or
git switch -c
Otherwise, use git checkout NAME
, a basic navigational command for a repo. A new alternative for navigation is git switch NAME
, which has the advantage of allowing you to return to your previous repo with git switch
.
To transfer a local branch to a new remote repository, the remote repository must first be recognized by the local one with:
git remote add REMOTE-REPO-URL://LOCAL-HOST/USER/repo.git
Then a local branch can be uploaded remotely with:
git push REMOTE-REPO-URL LOCAL-BRANCH
The new branch is automatically created as a sub-branch of the current one. At the same time that you move to the new branch, so does HEAD
(the current branch pointer). Keep in mind, too, that when you change branches, you change the versions of the files available to you. Should you forget, your Git repository can abruptly become a puzzling place.
Especially with large projects or numerous contributors, Git repo trees can have considerable depth and breadth. In such cases, navigating – just knowing where you are – can be a challenge. One solution is to use the command git branch --list
(Figure 1), which marks the current local repository with an asterisk and prints any checked out local repositories in cyan. Use -r
with --list
, and remote repositories are listed, while -a
lists both local and remote branches. Another navigational tool is to install the git-big-picture utility [5], which opens a map of the repository in a separate window (Figure 2).
Especially when merging (see below), you may also want to use git tag
to give each commit a human-friendly name and refer to Git's log. The log has an effective search function, and you can filter the branches with:
git log INCLUDED-BRANCH..EXCLUDED-BRANCH
Editing Branches
A commit's actual content is edited elsewhere – generally in a text editor. However, branches can also be edited and managed using the command:
git branch OPTIONS STRING
In this structure, STRING
can be a branch name or a commit, depending on the context. For instance, if a regular expression is used by itself, rather than a single branch name, then you could possibly create other branches – which could cause a lot of unwanted branches. To guarantee that you simply filter with a regex, --list
must be used as well. Another way to filter is to use --contains
to include only branches that contain the named commit (i.e., branches that are descendants of the commit) or --no-contains
to exclude descendant branches. Similarly, --merged
lists only branches merged into the named commit, while --no-merged
excludes merged branches.
One of the more common ways to edit branches is with deletion. The simplest choice is --delete
(-d
), but it only works if the branch is merged in its upstream branch, in HEAD
, or has a branch marked as its upstream (see below). If you are sure you want to remove the branch, use -D
instead, or combine --delete
with --force
(-f
).
Branches can also be copied with --copied
(-c
) or moved with --move
(-m
). The --move
option has the same restrictions as --delete
, but it can be forced with -M
or by being accompanied by --force
. If you want to rename a branch, you can use -m
(-M
) NEW-BRANCH OLD-BRANCH
.
A more complicated edit is to add --track
when a new branch is created. This option marks the current branch as being upstream from the new branch and is the default when working from a remote branch. In effect, it is a navigational marker, shown in git status
and git branch -v
. After a branch is created, you can give it an upstream with --setupstream-to BRANCH
(-u BRANCH
) or remove an upstream with --unset-upstream
.
More trivially, you can set how output is displayed. --color=WHEN
color-codes current, local, and remote repos, defaulting to always
but also taking never
or auto
as a value. To ignore whether characters are lowercase or uppercase, use --ignore case
. Another option is to display output with --column
or to use the verbose modes (-v
, --verbose
, or -verbose
) to see more information – although at the cost of having no columns.
Merging Branches
Merging is the joining of branches and the resolving of any differences between them. Before you merge, use git fetch
to make sure that any local or remote repos are in sync, and check that all changes are committed. Then check out the branch into which you want to merge and run git pull
to make sure it has the latest updates. Then enter the command:
git merge branch OTHER-BRANCH
If only one branch is specified, it will be merged into the current branch. When one branch is newer than the other, it will be marked as Fast-forward
, meaning it is a simple two-way merge (Figure 3) that will mark the differences in the branch being merged into and use minus signs to note differences in the branch being merged. In other words, the results are shown much as they are in the results of the diff
command.
Git does its best to resolve any conflicts, and, all going well, the result is a new commit into the parent branch that contains the original commits plus a log message detailing the changes. However, if there is no direct connection, Git tries to create one with a three-way merge, assigning a third merge as a route between the other two, which makes conflicts more likely. This is why a clear map of a repo can be useful. If you think a three-way merge is likely, you can add the option --no-commit
as a dry run to see what problems may emerge.
Since conflicts can be tedious to fix, especially in bulk, experts also suggest that you merge frequently. You may also decide to stop the merge with git merge --abort
, and Git will try to reconstruct the original change to all branches, although any uncommitted changes may not be restorable.
To fix conflicts:
1. Run git status
(Figure 4) to get a list of files that need to be resolved. In the files, <<<<<<<
marks the start of a conflict and >>>>>>>
marks the end. Use =======
to mark the start and end of your manual changes as you work. Contents from the first branch are marked in plus signs and from the second batch in minus signs. Delete the conflict markers when you finish editing.
2. Run the git add
command on the conflicting files when ready to merge.
3. Run git commit -m "MESSAGE"
or git merge --continue
to generate the merge commit.
If the conflicts are numerous or complicated, you may need to try a merge more than once to be successful.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.