Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Create a Git Repository and Branching Code

Learn how to create a Git repository and its master branch, then learn how to start new branches for things like additional app features.

Mar 4, 2019 • 13 Minute Read

Introduction

Today, it is not unusual to have programmers spread across buildings, cities, countries (and several time zones) while collaborating on one or more tasks. Distributed version control systems, such as Git, are what makes this possible - from the creation of an app all the way to adding, testing, and shipping new features.

This guide is not intended as a complete reference on Git, but as an overview of creating and working with repositories. As such, it assumes that the utility is installed on your system and that you are using a Unix-based operating system. If you are on Windows, Git commands are identical, and you will only need to modify some of the examples.

Introducing Git

Up until the early 2000s, software developers used to share their work from person to person. As more individuals were involved in the same projects, this approach became time-consuming, error-prone, and far from effective. Version control systems, a set of software tools that help teams share files and track changes over time, were born to address those needs.

In 2002, the Linux kernel community was among the first to adopt a version control system known as BitKeeper. Git was later devised by Linus Torvalds and launched in May 2005 after an open and public conflict on licensing terms between these parties. Two months later, a Japanese software engineer named Junio Hamano was appointed as the maintainer, a role that he still fills to this day.

Before we dive any further, it is worthy and well to define some common terms we will encounter later:

  • Web-based solutions, such as GitHub, Bitbucket, or GitLab, must not be confused with Git itself. These tools only provide space to store code in the cloud and a friendly interface to perform several operations. In this guide, we will use GitHub, but the process is very similar if you choose another solution.

  • A repository is a folder that contains the files and subdirectories of a project. It can be either public or private, depending on who should have access (anyone or only members of a team, respectively).

  • A branch is a separate development path (in the same repository) that is often used to work on new features without interfering with the main project. Once the code is reviewed and tested, a repository administrator can merge the changes into the master branch.

  • A commit is a snapshot of a repository at a point in time. It allows users to include comments and ask for feedback from other people. Using its hash, one can easily return to a previous state of the project if needed. Before file and directories can be committed, we need to instruct Git to track them. We usually refer to this step simply as adding or staging files.

  • A pull request is a method to inform other developers about and discuss recent changes before incorporating them into the main development path.

  • A fork is an independent project which is based off a given repository. Unlike branches, it is not local to the latter, but it can also be merged into it through a proper pull request.

  • A .gitignore file can be used to indicate which local content should not be committed to the repository. This is particularly useful to avoid pushing temporary files to or exposing sensitive information (such as passwords, SSH or API keys, and credit card numbers) in a web-based solution.

With that in mind, let us learn how to use Git and leverage GitHub for a software development project. Albeit simple, the following example will help us illustrate the basics of these utilities.

Creating a Repository

To begin, we will need to create a separate directory and then initialize Git on it:

      mkdir learn-git
    cd learn-git
    git init .
    

As shown in Fig. 1, the last command automatically placed us in the master branch and generated a hidden subdirectory called .git. This folder contains all the files and directories that allow Git to manage the repository.

At this point, we have a local working repository but have not added or committed any files yet. Before we do that, we will follow these steps to create an empty remote repository in GitHub where we will push our code.

  1. Click on the plus sign in the top right corner and choose New repository as seen in Fig. 2:
  1. Enter a repository name, an optional description, and choose Public as illustrated in Fig. 3. Do not initialize the repository with a README or add a .gitignore file at this point, as we will do that later - along with the license. Finally, click on Create repository.
  1. Copy the remote repository URL and take note of the suggested commands to push the local one over to GitHub through the command line but do not run them yet. Fig. 4 shows this step in our case.

We are now prepared to start adding files to our staging area and committing them.

Our First Commit

For this test, we will create a short Python file named disk_info.py with the following content:

      import shutil

    def disk_percent_usage(directory):
            '''
            Return percent usage of disk where directory resides
            '''
            disk_info = shutil.disk_usage(directory)
            return round(disk_info.used * 100 / disk_info.total, 2)
    

When this module is used, it is compiled to byte code in a file with the .pyc extension, usually in the same directory or in a subdirectory called _pycache_. In any event, we certainly want to include disk_info.py in our repository but not the associated .pyc file - and that is where .gitignore enters the picture.

To avoid keeping track of byte code files, we can add a single line to .gitignore as follows:

      echo "*.pyc*" >> .gitignore
    

With that, let us add both files (disk_info.py and .gitignore) to the staging area. Fig. 5 shows the difference in the output of git status before and after this step.

      git add disk_info.py .gitignore
    

The next step consists of committing the files to the repository. The -m option allows to include a message to describe the operation.

      git commit -m "Initial commit for Pluralsight guide"
    

Until files are committed as explained above, they are not part of the repository although they reside in the same directory where it is initialized.

Finally, push the local repository over to GitHub. Note that you will be prompted for your credentials as seen in Fig. 6:

      git remote add origin https://github.com/gacanepa/learn-git.git
    git push -u origin master
    

If we now browse to our GitHub repository, we should see the files as shown in Fig. 7. The commit hash is enclosed in a red rectangle and should be identical to the one that was returned by git commit earlier.

You can always view the changes that were introduced in a given commit via the URL for that commit. In the example above, it is https://github.com/gacanepa/learn-git/commit/1cbe0f3. Additionally, the full commit list (including messages, dates, hashes, and the user account who was responsible for each change) is available through git log.

Branching Code

So far, we have only used the master branch, which is where our production-ready program resides. If we want to add a new feature, we should consider creating a separate branch called development, although you can choose another name if you wish, and make changes there to start.

      git checkout -b development
    

The above command not only created the branch but switched us to it, as you can see in Fig. 8:

We can now open our text editor and create a new file named system_info.py with the following lines:

      import platform

    def kernel_info():
            '''
            Return Linux kernel information
            '''
            kernel_info = platform.uname()
            return {'release': kernel_info.release, 'version': kernel_info.version}
    

Next, we will proceed to stage the file, commit the change, and push it to the remote repository.

      git add system_info.py
    git commit -m "Added function to retrieve kernel information"
    git push -u origin development
    

To switch between branches in GitHub, we can use the dropdown list as illustrated in Fig. 9. If we select development, we should see the file we just added. Additionally, we can compare branches and create a pull request to merge development into master, but we will leave that for later.

Once our code is in GitHub, other developers can clone our repository to start working on it on their local machines.

Cloning a Repository

Before another developer can contribute to our repository, we need to add him or her as a collaborator in GitHub. To do so, we should go to Settings, click on Collaborators, and type the username or email address to send an invitation. Once our colleague accepts it, he or she will be able to:

  1. Clone the repository:
      git clone https://github.com/gacanepa/learn-git.git
    
  1. Switch to the development branch:
      git checkout development
    
  1. Make a change. In this case, we will add a README file using Markdown format:
      echo "# learn-git" > README.md
    echo "Check out my guide at Pluralsight" >> README.md
    
  1. Stage the file:
      git add README.md
    

If you need to add several files at once, you may want to stage the entire current directory with git add . instead.

  1. Make the commit:
      git commit -m "Added README.md"
    
  1. Push the file:
      git push
    

After making all these changes in the development branch, it is time to create a pull request for merging them into master.

Creating a Pull Request

To incorporate the latest changes to the master branch, we will raise a pull request. Although this can also be done through the command line, it is much easier in GitHub. When you click on Pull request, you will be taken to a page where you can view the list of the commits in development to be included and add comments as you can see in Fig. 10. Next, click on Create pull request to continue:

Finally, go to Pull requests and click on Merge pull request as shown in Fig. 11. Note that you will still be asked to Confirm merge afterward:

At this point, the master branch should be up to date when compared to development as you can confirm in Fig. 12:

Although it was not the case in this example, Git also provides a method to resolve conflicts between commits in the same branch if needed, as we will see next.

Resolving Merge Conflicts and Returning to Previous Commits

If a developer attempts to do a git pull after committing a file and there are discrepancies between his local repository and the remote one, a merge conflict occurs.

Generally speaking, a merge conflict arises whenever more than one person edits one or more lines in a file at the same time.

When this happens, an indication is added to the offending file(s) as you can see in Fig. 13. To resolve the conflict, you need to edit the file leaving the line(s) you want to keep, commit again, and push.

As we mentioned previously, Git also allows us to return to a previous commit if we wish. To do so, we can do git log to view the history and choose a specific snapshot using its hash. For example, to reset the status of master to what it was at commit 1cbe0f3, do

      git reset 1cbe0f3
    

This results in the changes that can be seen in Fig. 14:

Thus, README.md and system_info.py are still present in the current directory but were removed from the staging area after we ran the previous command.

Summary

In this guide, we have learned how to create a Git repository, work with branches, merge changes, and resolve conflicts. With these new skills, you will be able to work with other developers more effectively from here on out.