Git's branching model
Git encourages you to create branches, as they can be entirely independent of each other.
You can have the branches locally or in the remote repository. Very often, your local branches are actually connected to the remote one with a tracking mechanism.
This let's you work locally in your isolated working environment, commit to a branch, push it for others to check and then merge it in to a shared mainline branch.
They are called branches, as git creates a sort of tree structure out of the version controlled history. A tree works as a good metaphor too, when thinking about all your changes.
Creating a branch
Let's first create a branch locally. This is very easy in Git:
git branch my-first-branch
Note that this doesn't actually change you to the branch you just created!
You will have to checkout next:
git checkout my-first-branch
You can also combine the two by using the -b
switch for git checkout
:
git checkout -b my-second-branch
Which branch you are now in? You can check with git status
or see all branches with git branch -v
:
git status
git branch -v
Example after creating both of the branches above and checking out the first one:
$ git checkout my-first-branch
Switched to branch 'my-first-branch'
$ git status
On branch my-first-branch
nothing to commit, working tree clean
$ git branch -v
master 8d1765a Initial commit
* my-first-branch 8d1765a Initial commit
my-second-branch 8d1765a Initial commit
As you can see from git status
and the star notation in git branch -v
that we're now in my-first-branch and all branches are equal.
The branch names can be anything you want, but commonly software teams use something like feature/adding-a-new-button
or bugfix/squashing-that-pesky-bug
to show what kind of change they are working on.
We're happy with the ones we have for now!
Making changes in a branch
Let's make some changes in a branch, so the branches we have start to diverge.
You know how to add
and commit
already, so create a new file called "another-file" with the editor of your choice and commit it in. Remember to check with status
in-between, so you see that everything is OK:
git add another-file
git status
git commit
Example:
$ git add another-file
$ git status
On branch my-first-branch
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: another-file
$ git commit -m "Added another file"
[my-first-branch 440c27a] Added another file
1 file changed, 1 insertion(+)
create mode 100644 another-file
If you now check with git branch -v
you can see that our branches have begun to diverge:
$ git branch -v
master 8d1765a Initial commit
* my-first-branch 440c27a Added another file
my-second-branch 8d1765a Initial commit
Continuing with changes
Let's make another change and this time to an existing file rather than adding a new one.
Edit the file called "my-first-version-controlled-file" and change the text you had in the file to anything you'd like. For example "Hello everyone!".
One of the most useful aspects of git, or any other version control system is the possibility to check what has changed. In git, you can use git diff
to see the change even before committing:
git diff
Example:
$ git diff
diff --git a/my-first-version-controlled-file b/my-first-version-controlled-file
index 6769dd6..a811e8f 100644
--- a/my-first-version-controlled-file
+++ b/my-first-version-controlled-file
@@ -1 +1 @@
-Hello world!
\ No newline at end of file
+Hello everyone!
\ No newline at end of file
After checking what changed, add
and commit
as usual:
git add my-first-version-controlled-file
git status
git commit -m "Changed the message"
Merging a branch
Most commonly, you and the team will have a shared mainline branch. SVN called this a trunk, which would continue the tree metaphor pretty well, but in git it's by default called master.
This is changing however, and could be anything from development to my-best-branch.
Whatever the name, you usually want to bring in changes from other branches to this shared mainline. Just so you have a common ground to work from with our team, or maybe to make releases from if you are working with software.
This usually happens by merging the changes. You can do this in multiple ways, but easiest to get started with is to git checkout
to the branch to want to merge to and then git merge
the branch you want to merge from:
git checkout master
As you can now see, all the changes you have made are gone! Luckily only from your working directory, they are safely stored in git so you can merge:
git merge my-first-branch
Example:
$ git checkout master
Switched to branch 'master'
$ git merge my-first-branch
Updating 8d1765a..095971e
Fast-forward
another-file | 1 +
my-first-version-controlled-file | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 another-file
After merging, both of the files and all changes are now in your master branch, just like we want.
If you want, you can run git diff
against a branch to see what has changed in comparison to that.
Example:
$ git diff my-second-branch
diff --git a/another-file b/another-file
new file mode 100644
index 0000000..2831a7b
--- /dev/null
+++ b/another-file
@@ -0,0 +1 @@
+Hello from this file too!
\ No newline at end of file
diff --git a/my-first-version-controlled-file b/my-first-version-controlled-file
index 6769dd6..a811e8f 100644
--- a/my-first-version-controlled-file
+++ b/my-first-version-controlled-file
@@ -1 +1 @@
-Hello world!
\ No newline at end of file
+Hello everyone!
\ No newline at end of file
Encountering your first merge conflict
Git branches are very easy to create and they are very lightweight in comparison with some other version control systems.
For the most part, merging in changes is straightforward, but sometimes a conflict happens. This is normal and happens in any team that is working on multiple things at the same time.
There's no silver bullet solution for solving a merge conflict, but let's try!
First checkout the other branch we created earlier:
git checkout my-second-branch
If you now check with git log
you see nothing about the recent changes to master or the other branch we just merged in.
Example:
$ git log
* commit 8d1765ac9252d7bc6ce96bc54ecb685732ec2839 (HEAD -> my-second-branch)
Author: Miika Kankare <miika.kankare@polarsquad.com>
Date: Tue Apr 27 15:48:58 2021 +0300
Initial commit
This is OK, as you remember that we branched out before making any changes to the other branch!
Let's make a change to the "my-first-version-controlled-file" again, and this time set the message to say hello best friend or neighbor:
Example:
$ git diff
diff --git a/my-first-version-controlled-file b/my-first-version-controlled-file
index 6769dd6..d0ac400 100644
--- a/my-first-version-controlled-file
+++ b/my-first-version-controlled-file
@@ -1 +1 @@
-Hello world!
\ No newline at end of file
+Hello Bob!
\ No newline at end of file
$ git add my-first-version-controlled-file
$ git commit -m "Saying hello to Bob"
[my-second-branch 20aa465] Saying hello to Bob
1 file changed, 1 insertion(+), 1 deletion(-)
We have now committed yet another change and would like to merge to the master once again.
Checkout and see what happens:
git checkout master
git merge my-second-branch
Catastrophe! Someone had changed the same file!
Example:
$ git checkout
$ git merge my-second-branch
Switched to branch 'master'
$ git merge my-second-branch
Auto-merging my-first-version-controlled-file
CONFLICT (content): Merge conflict in my-first-version-controlled-file
Automatic merge failed; fix conflicts and then commit the result.
For the most part, when you change differing lines in a file with a co-creator using the same repository Git can figure out what to do when merging.
It is changes like these, that touch the same line in multiple commits that cause a conflict. It is now the user's job to sort out the conflict and continue onwards.
This time, let's abort the merge with git merge --abort
:
git status
git merge --abort
git status
Example:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: my-first-version-controlled-file
no changes added to commit (use "git add" and/or "git commit -a")
$ git merge --abort
$ git status
On branch master
nothing to commit, working tree clean
Next
As mentioned earlier, Git is very often used within a team. It is very useful for a single user as well, but very powerful with its branching model when used on a larger scale.
Let's continue on to using a remote repository