Git branches allow us to make changes to a repository, without changing the main branch. This way we can commit new changes and leave the current version unchanged until we are ready to merge the changes into the main branch. Making it great for working in parallel.
By default a repository will have a branch with the name “master”. We can consider this to be the main branch. In most cases there will be other branches as well. Such as “development”.
To get a list of all local branches you can use the “branch” command:
$ git branch
Local branches are branches you have already checked out. There are also “remote tracking branches”. These are branches that reside on the remote and have most likely not been checked out yet. You can see them by executing:
$ git branch -a
They are prefixed with “remotes/<remote-name>/”.
To switch to another branch you can use the checkout command:
$ git checkout <branch-name>
When you have uncommitted changes that would be overwritten by checking out this branch, you will receive a notification stating that you cannot switch to the branch because you have uncommitted changes. To resolve this you can either commit your changes or stash them.
See the section about stashing to find out more.
A new branch can be created by using the following command:
$ git branch <branch-name>
This will create a new local branch with the given name. However you will still be working on the same branch you were on.
To create a new branch and switch to it right away you can use the following command:
$ git checkout -b <branch-name>
Of course it is also possible to delete a branch, you can do this by executing:
$ git branch -d <branch-name>
This only works if the branch is up-to-date. This means that if it is a branch that exists on the remote, everything has to be pushed.
To force the deletion of a branch (maybe because we don’t want to push the changes to the remote), we can use the following command:
$ git branch -D <branch-name>
We can also rename branches, which can be very useful when we discover we have made a typo after committing changes:
$ git branch -m <old-branch-name> <new-branch-name>
At some point you will want the changes or rather commits to be available on the remote (server). This way other developers can see your commits and pull them into their local repository. To do this you can use the following command:
$ git push <remote-name> <branch-name>
For <remote-name> you will usually use “origin”, which is the default remote name.
Sometimes someone already pushed changes to this branch before you. When this is the case you will receive a notification stating that you need to pull first. While it is possible to force a push using an option to the command, you should never force a push!
Sometimes you will be working together with others on the same branch. To retrieve the changes that others have made, you have to use the following command:
$ git pull <remote-name> <branch-name>
This will go fine in most cases, except when someone has changed the same lines in a file you have changed. You will then be presented with a “merge conflict”. More information about conflicts can be found in the section below.
At some point the task that required making a new branch will be complete and we would like the changes to be integrated in the main branch.
There are 2 ways of doing this (always from the branch we would like to merge to):
$ git checkout master
$ git merge development
$ git push origin master
Or:
$ git checkout master
$ git pull origin development
$ git push origin master
Both will accomplish exactly the same, merging the development branch into the master branch.
Make sure your local branches are up-to-date before doing this.
When you make changes to a file and someone else has changed the same lines in that file, you will end up with a merge conflict. You will need to resolve this yourself. Git cannot decide which changes are correct.
Let’s say we have a php file that looks like:
<?php
class Test
{
public function __construct()
{
…
}
}
For a certain task one of your team mates had to add a constructor argument, making the file look like:
<?php
class Test
{
public function __construct($someArgument)
{
…
}
}
He commits the changes and pushes them, but while he did this you were working on a task that requires you to add a constructor argument as well, making the file look like:
<?php
class Test
{
public function __construct($yourArgument)
{
…
}
}
When you commit and push this change, it would be very bad if Git would simply overwrite your team mate his change with yours. So at this point Git will tell you it cannot merge your change and give you the opportunity to merge this change manually.
The file will look something like this:
<?php
class Test
{
<<<<<<< yours:Test.php
public function __construct($yourArgument)
=======
public function __construct($someArgument)
>>>>>>> theirs:Test.php
{
…
}
}
In this case you will probably want to have both arguments so you would edit the file to look something like:
<?php
class Test
{
public function __construct($someArgument, $yourArgument)
{
…
}
}
Now when you save and commit this, your conflict will be resolved. Do not forget to push these changes, so that the chance of having another conflict will be as small as possible.
Another thing to consider doing, when working on the same branch, is to always pull before you start working on a task. That way you will always have the latest changes on your local branch.