DEV Community

Cover image for Working with Git Branches and Pull Requests
Erika Heidi
Erika Heidi

Posted on

Working with Git Branches and Pull Requests

Git Branches Overview

Git branches are an essential feature of the Git version control system. They allow developers to work on different versions of a project simultaneously without affecting the main branch. Branches also enable multiple developers to work on the same project without interfering with each other's work. By creating a branch for each task or feature, developers can work independently and merge their changes back into the main branch when they're ready. Branches also facilitate tracking changes and reverting to previous versions of the code if necessary.

Working with Git Branches, a visual representation of branching

So far, we have only worked on the main branch. It is a convention to use main as the default branch where the most up-to-date version of a project can be found. Active development typically occurs in separate branches that are later on merged into main. Software releases are also typically based on the main branch, although it is possible to maintain several branches with different versions of a software.

The Pull Request Workflow

In the previous chapter of this series, you cloned a remote Git repository, made changes, and pushed the changes back directly into the main branch. In a collaborative workflow, you would be making changes to a separate branch (for example, readme-updates), then push this branch to the remote repository, and then open a pull request (PR for short) to request that your readme-updates branch be pulled or merged into main. Another collaborator would then be able to review your pull request before the changes are merged. GitHub offers several tools and even AI assistance for pull request reviews, which can be very helpful when working with teams.

If you are just starting and working solo on a project, you might wonder why you should care about pull requests at all. Here's why practicing this workflow is advantageous for beginners:

  • Better understanding of how branches and merging work
  • Preparation for contributing code to existing projects
  • Familiarization with the process of reviewing and approving pull requests

Undoubtedly, GitHub stands as the preeminent code platform in the market, making it imperative for you to acquaint yourself with its workflows and diverse features. It’s very likely that you’ll need to use this platform eventually, either for work or for academic purposes. So starting early might give you an advantage that others don’t have.

Creating your First Pull Request

We’ll now repeat what we did in the previous article, where we pushed some changes to your profile README directly from your local machine. This time around, however, we’ll work on a separate branch, and push this branch over to upstream. Then, you’ll open a pull request to learn how that works.

If for some reason you don’t have the project on your local machine, start by cloning the repo. You can obtain the SSH URL for the repository in its GitHub landing page by clicking on the green “Code” button. The URL follows this pattern: git@github.com:username/repo.git. Once you grab that URL, run git clone from your home directory and then cd into the newly created folder:

git clone git@github.com:boredcatmom/boredcatmom.git
cd boredcatmom
Enter fullscreen mode Exit fullscreen mode

If you’ve followed along with the previous guides, you should have a single README.md file in your repository. You’ll now create a new branch based off of main before you start making changes to your file. To do so, run the following command:

git checkout -b readme-updates
Enter fullscreen mode Exit fullscreen mode
Switched to a new branch 'readme-updates'
Enter fullscreen mode Exit fullscreen mode

The git checkout command is used to switch between branches. To create a new branch, use the -b parameter. If the branch already exists, use just git checkout branch-name to make the switch.

Now make some changes to the file. When you’re finished, proceed with the workflow of adding files to staging and committing changes:

git add README.md
git commit -m "updted"
Enter fullscreen mode Exit fullscreen mode
[readme-updates 8c8f620] updted
 1 file changed, 1 insertion(+), 1 deletion(-)
Enter fullscreen mode Exit fullscreen mode

Now, push the changes to upstream. Instead of pushing to main, thou, you’ll be pushing it to a branch with the same name as your local branch:

git push origin readme-updates
Enter fullscreen mode Exit fullscreen mode

You’ll get output similar to this:

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 1.31 KiB | 1.31 MiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'readme-updates' on GitHub by visiting:
remote:     https://github.com/boredcatmom/boredcatmom/pull/new/readme-updates
remote:
To github.com:boredcatmom/boredcatmom.git
 * [new branch]     readme-updates -> readme-updates
Enter fullscreen mode Exit fullscreen mode

As you can notice from the output, there’s a special URL you can access to create a pull request based on this branch. You can also simply access your repository page on GitHub and a prominent dialog will appear asking if you want to create a pull request based on the new branch that was just pushed:

Repository with unmerged changes

Click on the “Compare & pull request” button to open the pull request form. You’ll see a page similar to this:

Image description

The select box on the top of the screen lets you select the source branch and the target branch for the pull request. Typically you won’t need to change this. The PR form uses your commit message as title, and has a text area for you to describe the changes you are proposing and adding any relevant information to help test and review the pull request.

The bottom area of the pull request form shows a diff view of what has changed in this branch when compared to main. Red-highlighted lines are removed lines, and green-highlighted lines are new additions to the file.

Click on the green “Create pull request” button to create the PR. You’ll be redirected to the newly created pull request page:

pull request form

Congratulations! You have created your first pull request.

Reviewing a Pull Request

The process of reviewing a pull request varies greatly depending on the project, company, and/or team. In general, you’ll be looking at the “Files changed” tab of the pull request page, where you’ll be able to find all changed files with a rich diff that enables you to quickly visualize what was changed in that PR.

The GitHub interface allows for directly making comments and suggestions in the “Files changed” tab. Click on the blue + sign that shows up on each line (when you hover your mouse over that little space between the line number and the beginning of the line) to open the comments / suggestions form:

suggesting changes

To approve or request changes to a PR, click on the green “Review changes” button on the top right to access the PR approval form. Because PR authors cannot approve their own pull requests, you won’t be able to use the form to review your own PR, as you can merge it directly to main when you’re ready.

pr approval

Merging a Pull Request

When the PR is good to merge and there are no issues such as conflicting changes, you can click on the green “Merge pull request” button, and GitHub will merge the pull request into your main branch.

merging a pull request

Updating your Local Repository

When pull requests are merged through the GitHub interface, a new commit is created in the main branch carrying the changes that were merged. Your local copy of the repository will be outdated, with the main branch still pointing to a previous commit.

Start by switching to the main branch:

git checkout main
Enter fullscreen mode Exit fullscreen mode

To pull the changes and update your local main branch, run:

git pull origin main
Enter fullscreen mode Exit fullscreen mode

This will make sure any additional changes made from other authors or directly from the GitHub interface are pulled into your local repository. You should get output similar to this:

remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (1/1), 885 bytes | 885.00 KiB/s, done.
From github.com:boredcatmom/boredcatmom
 * branch           main    -> FETCH_HEAD
   26edb28..d42543d  main       -> origin/main
Updating 26edb28..d42543d
Fast-forward
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Enter fullscreen mode Exit fullscreen mode

If you run git log now, you should be able to confirm that your local main branch now points to the commit that merged the pull request from the readme-updates branch:

commit d42543de4d1ed7ec2c96c35500986ac882b94f3d (HEAD -> main, origin/main, origin/HEAD)
Merge: 26edb28 8c8f620
Author: boredcatmom <boredcatmom@hotmail.com>
Date:   Tue Nov 19 15:20:33 2024 +0100

    Merge pull request #1 from boredcatmom/readme-updates

    Updated
Enter fullscreen mode Exit fullscreen mode

It’s important to keep your main branch always up-to-date with your upstream, in order to avoid merge conflicts and other issues.

Sending PRs to Other People’s Projects

When working on other people's projects on platforms like GitHub, you'll often need to fork the repository to your account before you can make changes. This is because you don't have direct write access to the original repository.

Forking a repository creates a copy of the original repository in your account. You can then make changes to your forked repository without affecting the original. Once you're finished making changes, you can submit a pull request to the original repository. This will notify the original repository owner that you have changes that you'd like them to consider merging into their repository.

For more information on forking repositories, check the official GitHub documentation.

Appendix: Merge Conflicts and Common Mistakes

Despite its seemingly simple commands, Git can be quite tricky at times. Its complexity stems from the intricate web of branches, commits, and merges that it manages. Let’s review common issues in this short appendix.

Merge Conflicts

A merge conflict occurs when you try to merge two branches that have conflicting changes to the same file. This can happen when multiple developers are working on the same file at the same time and make changes that overlap. Although slightly annoying, merge conflicts are a very common occurence in Git world, so it’s nothing to be scared of.

When a merge conflict occurs, Git will stop the merge process and display a message indicating which files have conflicts. You will need to resolve the conflicts manually before you can continue with the merge. Merge conflicts also prevent maintainers from using the GitHub interface to merge pull requests, requiring manual intervention.

Git adds special markers on conflicting files so that you can identify the differences and choose which version you’ll keep. After you’re finished with the changes, you can continue with the merge process.

Please refer to the official GitHub Documentation for detailed resources to assist with merge conflicts.

Common mistakes when working with Git

We all have done it before, and we may still do it again sometimes! These common mistakes can cause issues such as merge conflicts, data inconsistency, or increased security risks.

  • Pushing to the wrong branch: if you try to push your local branch to a remote branch that doesn’t match your history, you’ll likely get a write error message, or you may end up with several merge conflicts.
  • Forgetting to add files to the staging area: you can only create a commit if you have files in staging. Also, be mindful of what you’re adding to the repository. You can use a .gitignore file to add files that should be ignored.
  • Accidentally deleting or overwriting files: it may happen that you delete a local file by mistake and accidentally commit that change to the repo. That’s why it’s important to pay attention to what’s in stage before creating your commits.
  • Accidentally committing files with sensitive information: this can pose a serious security risk to a project or user. Files with sensitive information such as passwords and tokens should never be committed to the repository. Add any files with sensitive data to your .gitignore.
  • Pushing local changes without pulling remote changes first: the most likely outcome of pushing local changes without pulling updates first is a merge conflict. Always remember to update your branches before pushing to origin.
  • Forgetting to push changes to the remote repository: sometimes we just forget to hit that final push and send the changes to the repository. Not a big deal, but a very common thing to happen 🙂

Conclusion

In this guide, you learned about branches and the mighty Pull Request workflow. Hooray! You have now the basic tools to start building on GitHub, and to start contributing to open source projects, if that’s something you’re interested in. Coding can definitely be more fun with friends, and luckily for us, GitHub is an excellent platform to build projects together just like that.

With that, our Git and GitHub Crash Course comes to an end. Here are some resources you may refer to if you want to learn more about Git and GitHub:

Top comments (0)