Introduction To Git/Version Control

Often when working on programming projects, we work in teams and we want to have access to older versions. Perhaps the most common way to meet both goals in industry is to use a type of program called "version control." In this tutorial, we will discuss one way of collaborating on teams with version control using a system called Git.

What is Git?

One of the most common methods of collaborating and tracking work is through a version control system, like Git. Git's purpose is to make continuous backups of code, to provide easy access to those backups and to coordinate changes made by different people so that everybody stays synchronized. The general idea is to make it more difficult to lose work that is being completed on a project and to be able to quickly revert to previous versions. Given that real-world projects are almost always completed on a team, Git also allows collaboration among many programmers on a single project. The system works by having a common repository stored on a networked server which keeps a master copy of the source code and project files. Team members can "pull" a copy to their local environment, which means they download a copy of the code from the web to work on. Once developers obtain the source code, they can make changes and send them back (through a process called committing and pushing). Doing this by hand, by emailing files back and forth for example, would be complicated and prone to error. Git handles all of this for us automatically.

Getting Started

Git is already supported in Netbeans and is built in to the user interface for Quorum. Before we can start using Git, however, we need to download a copy of the code "repository." A repository is a set of files online that we can pull (download) from and push (upload) to. Several websites are available to store shared code repositories, including two of the more common ones: Github and Bitbucket.

Bitbucket

Bitbucket is one of the most popular websites used to host Git repositories. Bitbucket allows users to have unlimited public and private repositories for teams of up to five people. To sign up with Bitbucket, navigate to the Bitbucket website and use the the Get Started link at the top of the page. Once there, we will need to enter our information to make an account.

Github

Github is another popular option for hosting Git repositories. To sign up with Github, we can navigate to the Github website and select the Sign Up link at the top of the page. Again, we enter our information to create the account.

Starting a Repository

Before we can start using Git to manage our project, we need to set up a location on our Bitbucket or Github account for our code to go. To do this, we need to create a repository on our Bitbucket or Github account for our project.

If we are using Github, look for the link that says "+ New repository." This link is located above the list of any already-existing repositories we may have.

This is an image of the new Repository Github

If we are using Bitbucket, the link to create a new repository is under the Repositories navigation bar. Select "Create Repository" and then follow the instructions to create the repository. (The keyboard shortcut to create a new respository is: "c" and then "r")

This is an image of the new Repository Bitbucket

Follow the instructions and fill in the necessary information in order to set up the new repository. Typically, it will ask for a repository name and whether the repository is public or private. A private repository is a repository that can only be seen by people that you specifically give access to. A public repository is a repository that can be viewed by anyone.

Cloning a Repository

Once we have a repository created on Bitbucket or Github, we need to get a copy of it on our local machine by "cloning." Cloning a repository downloads all of the files from that repository, typically from the Internet. To clone a repository, we first locate it (or one from another person) and then we look for its address. Just like websites, git repositories have their own address. In Bitbucket, this link is located at the top of the page of the repository towards the right. In Github, i t is also located near the top of the page towards the right. Here's an example of a repository:

https://bitbucket.org/stefika/quorum-language.git

The above is the Git repository for Quorum itself.

This is an image of the cloneBitbucketThis is an image of the cloneGithub

First, copy the link to clone the repository from the browser and then switch to Netbeans, go to the Team tab in the Menu bar and under Git, select Clone.

This is an image of the netbeansClone

In the pop up window, add the link you copied from the repository in the box for Repository URL, the username and password for your Github or Bitbucket account and the location to save the repository. When complete, select next.

This is an image of the cloneRepo

In the next window that appears select the branch you wish to use. In the screenshot, the "Master" branch is selected. In simple projects we often only have a single branch, so we can usually just select Master. In more complicated projects, however, branches are used to provide alternate versions of the code, often during development of new features.

This is an image of the cloneBranch

Finally, you are asked to chose a parent directory and a name for the cloned project. Clicking finish allows us to clone the project.

This is an image of the cloneDestination

Once the project is cloned, a pop up window will ask if you wish to open the project.

This is an image of the openClone

Adding/Removing Files

When we create new files, Git needs to be told to track these new files in the repository. Fortunately, Netbeans automatically informs Git to add or remove any files from our repository depending on our changes.

Committing

After we have finished modifying a file, we are ready to send our changes back to the server. This involves a two-step process: 1) committing, and 2) pushing. Committing tells Git that we want to store a new version locally, meaning on our machine. We can think of a commit like a "snapshot" of our project at a particular time (e.g., version 1, version 2, version 3). To commit changes to a project, we open the Team tab in the navigation bar, then select Commit.

This is an image of the commitButton

A pop up window will ask us to add a commit message. A commit message is something we write to remind people what was changed. Keep in mind that messages written are public, meaning anyone on the project (e.g., our teacher, our friends, the world) can see them. As such, we should keep commit messages respectful.

This is an image of the commitMessage

Below the box for adding a commit message is a list of all the files we are committing changes to. NetBeans provides us this list to help identify what was changed in our new versions. If there is a file here we don’t want to save changes to, we can uncheck the checkbox next to the file. In the list, a green filename is a newly added file and a blue filename is an existing modified file.

This is an image of the commitFiles

Clicking the commit button completes the commit. We have now saved our "snapshot" of our project.

Pushing

Typically, after committing changes to a project, we want to send the source code back to the server. We call this a "push." A push is an action that takes the files of our project from our local computer and uploads them to the repository, usually one located on the Internet. In our case, this other repository is on the server at Bitbucket or Github. Once the repository is pushed our files are backed up and protected if something were to happen our computer. As an additional benefit, by regularly committing and pushing our files back to a server, others on a software development team can obtain our updates by doing a pull.

To push, we use the Team tab in the Netbeans Navigation bar, select Remote, then select Push. A pop up window will appear. If this is our first time pushing a commit for this project, the window will ask us where our repository is. We can paste the link from the repository in the Repository box. Then, we can enter our Bitbucket or Github username and password, which will allow us to make the change. Click next.

This is an image of the pushWindow

At this stage, a window will now appear asking us to choose which local branch to push to the repository to. Most likely, there will only be one option, called "master," which we will leave as the default. Click next.

This is an image of the pushBranchLocal

Another window will appear asking us which remote branch to push our code to. Again, for this tutorial there is only one option, which we leave as it is. Next, we select the Finish button.

This is an image of the pushBranchRemote

One final window will appear for this new repository. This window asks us to confirm whether we want to create the link between our own local (on our computer) repository and the remote (on another computer, like the servers for our Github or Bitbucket account) repository. We want to be able to send the code back to the server, so we select yes.

This is an image of the pushLink

We have now completed our first push! Our team members can now get access to the code we've been writing by cloning if they are just setting their project up for the first time. If they already have the project repository cloned on their local machine, they can update with our changes by "pulling" the current version of the repository, which we will talk about next.

Pulling

Similar to how pushing is the way to upload our changes to the repository, pulling downloads the latest updates from an existing repository to our local machine. Typically, when other team members are writing code and pushing it, we want to stay up to date, so we pull down the changes, integrate them into our local project, and then push back our own changes.

To pull a project, under the Team tab in the Netbeans navigation bar, select Remote and then Pull. A pop up window will ask us to specify the remote Git repository location. If the repository is not already set up, paste the link to the box and select Next.

This is an image of the pullWindow

Like before, for this tutorial, the only option in our next window is Master, the default. We continue by selecting Finish.

This is an image of the pullBranch

With pushing and pulling, it is often customary to pull from a repository when we start working on the project for the day. When we make any important changes that we want to keep, we commit those changes. When we are done working on a project for the day, we push all of our changes to the remote repository. This is not required, but it's a reasonable and typical way to control source code on a project.

Merging and Merge Conflicts

Occasionally when working with Git, we encounter Merging and Merge Conflicts. These can be confusing and are caused by multiple team members changing the same files in the repository. They can be avoided by team members being aware of what parts of the code they are working on in comparison to their colleagues, to prevent overlap. They can still come up though, so we need to know how to resolve them.

When we push or pull from a repository, Git tries to reconcile all the differences between the code in the two locations, that is, the code on our computer and the code on the remote one. Most of the time, it is able to tell where differences are and how to put the two versions of the file(s) together. Sometimes, however, two or more versions have made changes to the same line, and Git cannot know which line is intended, so it can not properly merge the files. This is where a conflict happens.

In another situation, another team member pushed a change to a repository before we have done a new pull. This means we will need to do a merge commit to put multiple versions of a repository together. In this case, a pop up window will explain the situation. Selecting the Merge option on this window allows us to merge the two versions. In this window is a separate option called rebasing. Rebasing is an advanced topic that is rarely necessary and should be researched before attempting.

This is an image of the mergeNeeded

After selecting "Merge," if there were merge conflicts, another window will open telling us that the attempt to merge the two files produced one. It asks us if we want to resolve the differences manually. Select the option to review the differences.

This is an image of the mergeConflict
The file or files that caused the merge conflict are shown in the text editor of the IDE, and Git has made some additions to the file(s). These changes are marked by "conflict markers" which are a set of <<<<<<< HEAD and >>>>>>> origin/master with a ======= between them. The <<<<<<< marks the beginning or the part of the code where the conflict occurs and the >>>>>>> marks the end of the part of the code where the conflict occurs. Below the <<<<<<< HEAD line is the line or lines of code from our file that have caused the merge conflict. The two conflicting parts are divided with the ======= symbols. Below this line is the line or lines of code from the file on the remote computer that have caused the conflict. Below these line(s) is the >>>>>>> origin/master origin/master marking the end of the conflict area. We know that the symbols chosen here make little sense. Unfortunately, while version control can be very helpful, this is one of its quirks.This is an image of the mergeConflictUnresolvedWe now have a few options to fix the conflict. First, we must remove the conflict separators from our file; that is, we must remove the lines with the <<<<<<<, =======, and >>>>>>> symbols. We can then choose to keep our change to the file by removing the line or lines that our team member changed. Alternatively, we can choose to keep the change our team member made and remove the line or lines that we changed. A third option is to come up with a solution that keeps both changes if both changes are needed. We should follow these steps in order to resolve any other merge conflicts that exist. Once we are done resolving the conflicts, we should save our file to keep the changes.This is an image of the mergeConflictResolved

Once we have saved our file, we should commit and push our project so that all of our hard work in resolving the merge conflict is saved for everyone else to see. Committing and pushing after a merge conflict is the same as committing and pushing any other changes, so we follow the same steps. The only difference is that the commit message for a merge conflict by default says that it is a merge commit and which files caused the merge conflict.

Additional Information

Git is a very useful tool for software engineers to use, especially when working in teams.Git has plenty more capabilities than the ones mentioned here. There are a lot of resources on the Internet about how to use Git.Some useful resources are:


Pro Git book

This book, available online, provides a very in-depth description of what Git is and how to use it. It mainly focuses on using Git via the command line, though, which is harder than using it in an IDE.


Using Git in NetBeans

This site gives an overview of how to use Git in the Netbeans environment. It gives additional information on Git capabilities not mentioned in this tutorial.

Next Tutorial

In the next tutorial, we will discuss Android Mobile, which describes how to use Quorum on an Android device..