Branching and Merging

Basic Branching and Merging

The basic idea of branching and merging is to be able to take projects offline to do independent development or bug fixes with affecting the main trunk of a project.  In many cases this development can go on for an extended period of time and you want the ability to make minor changes and tweaks to the production version of the project without breaking it.  Lets run through an example of branching using the command line and merging it back into the main project.

To begin, run the command below to create a new branch:
git checkout -b branch01
(This is shorthand for git branch branch01 | git checkout branch01)

This will create a new commit line starting from the last commit in your repository.  There is a handy timeline tool in GitLab for visually seeing this divergence and convergence of branches.

Lets add a file to the project called index.html and commit it.
vim index.html (unix style text editor, you can use your favorite editor to create this file, this step doesn’t matter)
git add –all
git commit -m “Add new index.html file to branch”

Your screen should look similar to the image below:

branch1

Lets push this to the server before going any further.
git push origin branch01

During the work we did on this, another person made some changes to the master branch.  We now need to merge these changes together.
git checkout master
git merge branch01
git branch -d branch01
git push origin master

So what happened above is that we switched back to the master branch and merged it with branch01.  Whenever you finish with a branch, you should delete it to keep your repository clean using the -d flag on the branch command.  We then pushed the project back to the server.  If we look at the visual tool in GitLab, we can see what actually took place.

branch01

The timeline diverges at the fourth commit.  You can see the parallel development taking place before merging them back together.  If you coordinate your development correctly, this process will run very smoothly.  Occasionally however, you will run into merge conflicts that will need to be resolved before proceeding.

Basic Merge Conflicts

Lets look at the case illustrated below in the visual tool in GitLab.

branch02

Two people have been making changes to the project.  Person A created a branch and removed the word World from our index.html file.  At the same time, Person B has changed the word World to CITL.  What we are left with is a merge conflict for Person A who now wishes to merge their branch back into master.

conflict1

Here we see Person A has attempted the merge and the automated process has failed.  This is forcing us to go into the affected files and make the necessary corrections.

conflict2

What Git has done for us is place conflict-resolution markers around the code it could not auto merge.  At the top is the HEAD or master branch and at the bottom is branch02.  After a discussion with Person B, it was decided that Person A will remove their change and leave Person B’s change as is.  Ensure you delete the markers and only leave what you wish to commit to the repository.

conflict3

We are now ready to return to the command line and complete the merge.  To do this, run the add command on each file to tell git the conflict has been resolved:
git add index.html

git commit -m “Using Person B changes”
git push origin master
git branch -d branch02

Again, we will commit and push to the server along with deleting the old branch.  Lets look at the GitLab visual tool now.

conflict4

We can see that the branch has been successfully merged with the master and we no longer have any conflicts.

 

Basics

The Git Command Line interface is the most basic way to manage a repository.  The command line is cross platform, meaning whether you develop on Windows, Mac OSX, or Linux, the process remains the same.

Creating a Project/Repo
To begin, we will need to create a project.  In the GitLab interface, repositories are referred to as Projects as GitLab adds more functionality outside basic version control.  Git is referred to as a decentralized version control system.  The commits are local to your machine until a Push is made to send the changes to the repository server.  This is contrasted by Subversion which is a centralized version control system.  All the commits are made directly to the repository server.

Lets start by logging into http://repos.citl.mun.ca and clicking the New Project button:

new-project

From here, you will need to enter at minimum the name of the project.  By default, the project falls in your personal namespace which is hidden from others unless you explicitly give them permission to see it.  Clicking the drop down next to the project name will reveal a list of namespaces you have access to.  In the case of the Course Development team, you will see multiple groups with pre-defined access permissions.  This saves time setting up who can view/edit the project if they all fall into a similar category. See image below for example.

new

The visibility level should always be left private which you defining who has access.  In our deployment, the Public option will not work.

You will also notice that you can import a project from various other sources that use git for version control.  If you are working on a project outside GitLab but require it to be brought in, you can use the option to save time configuring a project from scratch and losing the commit history.

Although this is command line, this is a necessary step for future topics.  Now we need to create the repository locally so we can add files to it.

Open up the Git Shell (Windows) or Terminal (Mac/Linux).  Here we will want to navigate to the directory we want to create the repository in.  This can be done using the cd and mkdir commands.  For simplicity, we will create a folder in My Documents (Windows) called Repositories and a sub folder called the same as your project.

create directory

You will notice with GitLab, it really likes to help you along.  On your new projects Dashboard, you will notice it has instructions on setting up your repository.  The steps on this page have been executed below.

clone1

You have no successfully created a project and a local repository. You are ready to start managing code via Git.

Cloning a Repository
Cloning a repository is the process of initializing or downloading an existing project to your local machine.  To reiterate, Git is a decentralized version control system so a clone will copy the entire repository to your local machine.  It is isolated from the original stored on the GitLab server.

To clone a repository, you will need the origin URL.  This can be retrieved from the project dashboard in GitLab.  We will use the previous project we created as an example.  The steps are as follows:

  1. Create a directory where you want the repo to go.  (You can skip this step and it will use the project name for the directory, leave out the period at the end of the command if you wish to do this.)
  2. Run the command:
    git clone git@repos.citl.mun.ca:/a97jjw1/demo-project.git .

If you look inside the folder we created (or automatically generated), you will see all the files in the repository.  There is also a .git folder.  This contains all the information about the repository such as history, commits, merges, branches, etc.  Do not edit or delete this directory, it will break your repository.

Commit/Push
The commit/push commands are used to maintain versions of your code.  This is especially handy when making changes that may impact the overall system and you may need to revert back.  Commit is a local command and will not affect any other user.  It is recommended you commit often and not in huge lumps.  In order to commit you first must prepare any changes that have been made:
git add –all
The –all flag checks for changes in all files (edits,creations, and deletions) and prepares them for a commit. Now run the commit command:
git commit -m “Your Message Here”
The -m flag is for a description or message describing the commit.  You must add a message to every commit, it will fail if you leave out this flag.

If you are ready to send this code to the server (someone might need the code to work on or to ensure it is safely backed up), you can use the push command.  Before you can run the push command, you must have at least one commit made.  Only the changes in the commit are pushed to the server.  It is highly recommended you do a Fetch/Status/Pull of your repository before pushing. (Please see the topic on this below)  If you don’t, you may receive a number of different errors ranging from file conflicts to out of sync repository. (You may have an older repository than whats stored on the server.)

The syntax for a push to the remote repository is:
git push <remote location> <branch>

In most cases, the command will look like:
git push origin master

Origin refers to the remote location set when we did a clone/initialized the project while master refers to the primary branch of the project.  More advanced users may create a branch of their project to make changes without effecting the project.  This is particularly useful if you have a project in production.  You can branch off to develop a new feature before deploying it into production.  Please see the section on Branching/Merging for a more thorough description of this process.

Fetch/Status/Pull
When working with multiple users on a project, it is common practice to run these commands to ensure you get their changes.  Lets walk through this process.  In the below example, a change was made to the README.md file.

pullfetch

We first run git fetch.  This will check the server if there are any changes not in our repository.  This command will not always provide you with the necessary information to know if there are any changes to pull.  This is where git status comes in.  After running this command, we notice that our branch is behind by 1 commit.  Before we can push any of our changes to the server, we need to run git pull.  We see that the file README.md has been updated and our repository is now up to date.  If there are any conflicts, this will be noted here, please refer to the Branching/Merging topic for how to deal with these conflicts. (Known as a Merge)

Revert (Checkout/Reset/Revert)
There are two ways you can go back to a previous commit and it depends on your specific situation.  If you are looking to temporarily to go back and play around but wish to return back to the latest commit, the checkout command is what you need.  If you wish to delete previous commits, never to return to that work, the reset command is used.  The reset command only works locally so before you can do a push, you will need to do a pull and this is where it can start getting messy.  The command you really want to use is revert.  This will maintain the history but bring the commit to the HEAD (latest commit) of the project.

To run either of these commands, we first need to find what commit you want to revert back to.  This can be obtained from both the GitLab interface or by running the command: git log.

log

In this example, we will revert to the previous commit: 0c3e258a08910660a1d4bd6e1fb863ff983f826f.

checkout

If we run git log again, we will notice only the commits from this commit back are now listed.  This however is only temporary and any changes you make can’t be committed to the repository.  If you wish to make changes, the command you should run is:
git checkout -b <branch-name> <commit>

This command checks out the previous commit as a new branch.  You will need to merge this back into the project later to make it part of the master. (Please see the topic on branching and merging for a more in depth discussion on this.)

When you are finished playing with the old code, you can return to the HEAD (last commit) of the project by checking out the master:
git checkout master

We will ignore the reset command in this tutorial as it will rarely be used so lets have a look what a hard revert looks like.  We will bring an old commit to the head of the project and push the changes to the server.

revert

Let us walk through this.  The first command we run is:
git revert 0c3e258a08910660a1d4bd6e1fb863ff983f826f
This will initiate the revert process.  We will notice some errors start to pop up.  This will ask you to analyze any change that has been made after the commit we are referring back to.  If you open the file, you will notice sections/blocks of code indicating what commit they belong to.

<========================= HEAD

SOME CODE HERE

==============================>

It is up to you to clean this up before reverting.  Ideally you would delete all the blocks called HEAD as they are the latest commits.  You can avoid this step by conducting a git checkout 0c3e258a08910660a1d4bd6e1fb863ff983f826f first as this will take care of reverting the code back for you.

Once you have the corrections made, we run the commands:
git add –all
git revert –continue
Out project is now ready to be pushed to the server.

Going back to a previous commit will almost always cause some kind of problem with git that will need some minor troubleshooting.  Where CITL works mostly in small groups or independently on projects, it will be quite rare that we will need to use this procedure but understanding how you can go back is an important aspect of git version control.

Changing the Repository Origin

 

Generating a SSH Key – Windows

Generating a SSH key on Windows can really depend on what tool you are using to manage your Git repositories.  For CITL, we will focus on GitHub GUI.  This tool comes with two packages, a command line or shell and a friendly user interface.  Generating a ssh key with this tool is common for many Windows based Git tools.  To get started, lets open Git Shell.

gitshell

Please note that the initial location you see (J:\Repos in the image above) may not be the same on your machine, please ignore that for now.

In here, you will want to type the command:
ssh-keygen -t rsa -C “<Your Email Address>”

firstcmd

Leave the save location as is by hitting <Enter> and leave the passphrase empty.  After doing so, your screen should look like the image above.

Now you will want to print the key to the console so you can copy and paste it into GitLab.  Run the command:
cat ~/.ssh/id_rsa.pubB
(In many cases, you may need to put the full path:
cat c:\Users\<Your Username>\.ssh\id_rsa.pub

ssh_cat

Now you will want to copy this (right click the top bar where it says Windows Powershell) and click Edit->Mark.  Start at “ssh-rsa” and drag your cursor to the end of your email address.  Then right click your mouse to copy the text. (The white highlighting will go away indicating that you have copied the key)

Now, go to http://repos.citl.mun.ca, log in, and navigate to Profile Settings->SSH Keys and paste the key into the textbox called “Key”.  Before you click Add Key, the copy method we used will add line breaks to the key.  Ensure those are removed by clicking the start of each line and hitting backspace.  Your key should look like this when done:

key_repos

The Title can be named anything, I recommend you use something like <Username>-workstation.

Once the key is successfully added, you can test it by going back to the shell window and typing:
ssh git@repos.citl.mun.ca

The response should look like the image below:

ssh_success

As you can see above, a success message with your name will pop up indicating your key is working.  If you are asked for a password, the key did not add successfully.  Return to the top and walk through these steps again.  When removing the line breaks from the key, ensure you did not accidentally delete and of the characters, just because the key added to GitLab, does not mean it is the correct one.

What is a SSH Key?

In order to work on any Git repository from your computer, you will first be required to generate a ssh key. A ssh key is secure way way of connecting to a machine.  It does not require the use of a username or password and is unique to the computer you are using.

Introduction to GitLab Interface

interface

CITL’s GitLab is located at http://repos.citl.mun.ca.  It can also be accessed via the Hub’s quick link menu.

There are two main sections to the GitLab interface, the navigation pane (left) and the working pane (right).

The Navigation Pane

menu bar

When you first login, this navigation pane is global on all projects you are a member of. The numbers next to the sections “Todos”, “Issues”, and “Merge Requests” are tied to all your projects. For the most part, you will be focused on the Issues option. This is a handy place to view all ongoing issues in your projects and to make it easier to prioritize your work.

The option section to take note of here is your Profile Settings.  This is where you can configure such things as your SSH keys (required for working on any repositories), the user interface, and your personal information.

 

 

 

 

The Working Pane

Getting Started

What is Git?
By far, the most widely used modern version control system in the world today is Git. Git is a mature, actively maintained open source project originally developed in 2005 by Linus Torvalds, the famous creator of the Linux operating system kernel. A staggering number of software projects rely on Git for version control, including commercial projects as well as open source. Developers who have worked with Git are well represented in the pool of available software development talent and it works well on a wide range of operating systems and IDEs (Integrated Development Environments).

Having a distributed architecture, Git is an example of a DVCS (hence Distributed Version Control System). Rather than have only one single place for the full version history of the software as is common in once-popular version control systems like CVS or Subversion (also known as SVN), in Git, every developer’s working copy of the code is also a repository that can contain the full history of all changes.

In addition to being distributed, Git has been designed with performance, security and flexibility in mind.
(Sourced From: https://www.atlassian.com/git/tutorials/what-is-git/)

What is GitLab?

GitLab’s core functionality is to assist in coding, testing, and deploying code together. It provides Git repository management with fine grained access controls, code reviews, issue tracking, activity feeds, wikis, and continuous integration.

For CITL’s purpose, we tend to omit many of the advanced features and use it as a code repository and for project bug tracking. In 2015, we replaced Mantis Bug Tracker with GitLab in order to streamline development.