How To Manage A Shared Codebase. Avoid common problems faced when... | by Cody Nicholson | Towards Data Science

Congratulations! You’ve finally come up with the perfect new app idea. You and your team of software engineers rush into writing the code that will be your ticket to fame and fortune. But wait. The code Maria wrote for the homepage of the app looks great — but how will that work with the code Steven wrote for accessing the database? And Hector put together a function that calculates the values we are looking for — but how will those values move from one page to another in the app? It has become a project in itself to make the team’s code work together!
In this article, I’m going to show you how we can use Git and GitHub to manage a codebase that will be shared among multiple developers. Version Control tools like Git are used by: Software Engineers, Data Scientists, and Game Developers — just to name a few.
PREREQUISITES: Install Git, Have a GitHub Account, Know how to create a repository
Once you are logged in on GitHub go ahead and create a repository. Mine will be called “How_To_Manage_A_Shared_Codebase_Article”. Make sure you create your repository with a README.md file so that you have a root commit before you go to step two. In your newly created GitHub repository, click Settings. Then choose Collaborators from the left hand menu.
You can add your team members by their GitHub Username or their Email Addresses. They will then receive an invitation to join your project via email.
Once they accept you will be able to edit their permissions on the collaborator page by selecting from the options:
Now you and your team can clone your repository and begin developing! If you gave your team members “write” permission they can begin contributing.
A Branch in Git behaves like a copy of the project that we use to organize the segments of work. If we have three tasks to complete on our project — we can create a branch for each task and then merge each branch into the main branch when we finish each individual task.
In our newly cloned repository try running the command:
git branch
The git branch command lists the branches we have in our repository. Currently, we only have the default main branch that was created automatically when we created the repository. We can make a new branch using the git branch command with an added branch name like this:
git branch first_branch
We now have what will behave like two unique copies of the project. The main branch has a star next to it — meaning this is the branch of the project we are currently using. To switch between branches of the project we use the git checkout command:
git checkout first_branch
Now if we run the git branch command, we’ll see the star has moved from main to first_branch:
On our new branch, let’s add some changes. We’ll create a shell script called app.sh that contains:
echo “Hello world”
Then we’ll add the file and commit it. After, we can run git log to see our new commit:
NOTE: See on the second line I run the app.sh file on Windows using “./app.sh”. On Mac or Linux you would use “sh app.sh” to run the file.
Now let’s use git checkout to go back to our main branch and then use git log to see our commits on the main branch:
As you can see, the commit we created on our first_branch branch isn’t here. Let’s assume that the work we were doing on first_branch is done, and now we would like to move our changes to the main branch. For that we will have to switch back to our first_branch and push our branch to GitHub.
Running git push on our first_branch will fail — but it will provide the command we can use to set our upstream. Since we created our branch on our local repository and we never pushed this branch until now — our new branch doesn’t know where to push to. We set the upstream as origin by running the command it gives us in the error message when we try to push: “git push --set-upstream origin first_branch”.
Let’s go back to GitHub to see our new branch that we pushed. We can change the branch we’re viewing using the “Branch: main” drop-down menu on the bottom left in the below picture. Since we have just pushed our branch, GitHub gives us a message asking us if we would like to create a pull request with our new branch. We’ll click the green “Compare & pull request” button.
Now you can see that first_branch will be merged into main denoted as: base: main ← compare: first_branch. Next to that there is a green “Able to merge” message telling you that these branches can be automatically merged. Click on the “Create pull request” button to create the pull request.
The next page — as seen in the below image — is the newly opened pull request’s page. You can view what was changed on the first_branch by clicking the “Files changed” toolbar option. Since the changes we made did not result in any conflicts, we can click the “Merge pull request” button and Git will automatically merge our code into the main branch.
Using pull requests to merge code into the main branch requires this long process because we want to ensure that broken code never ends up on the main branch.
Since we merged the first_branch into the main branch on GitHub, our main branch online is now updated with the code from our first_branch. However, our repository on our local machine doesn’t know about this update to our main branch. In order to sync up the main branch on our local machine with the main branch online we will “git checkout main” to switch back to our main branch and then use the “git pull” command to get the updated changes:
In the message you can see that one file has changed and it is the newly added app.sh file from the first_branch that we merged to main.
This merge was easy because we didn’t have any conflicts. How would we resolve conflicts if two developers made conflicting changes to the main branch?
In the below image you will see I first create two branches off of main: second_branch & third_branch. Then I switch to the second_branch and I change the message from: “Hello world” to “Hello world from second branch!”. Now that I have made this change, I “git add .” to select all the changes to be committed, then I “git commit -m ‘update app.sh’” to create the commit on second_branch. Then I try and “git push” knowing it will fail since I have not set the upstream — but it will give me the command to set the upstream and push my second_branch to GitHub for the first time:
The current state of the project is that the main branch still has the app.sh with the message “Hello world” while the second_branch has the updated message of “Hello world from second branch!”. We have pushed our second_branch. If we wanted to, we could merge second_branch into main right now with no conflicts exactly how we did it the first time. However, we want to simulate a conflicting change. Back in our terminal or git bash let’s switch to third_branch and add another change:
In the above image you’ll see I switched to third_banch and changed the message “Hello World!” to “Hello from third branch!” in the vi editor. The message was “Hello World!” because we created third_branch as a copy of the main branch — and it has no idea about the changes that we made on the second_branch. After setting our upstream and pushing our third_branch to GitHub, our GitHub page will have a “Compare & pull request” prompt for each of our two updated branches as seen below:
Let’s merge second_branch first. We click the corresponding “Compare & pull request” button and then we see the green “Able to merge.” between main & second_branch on the next page:
We click the green “Open pull request” button and then click the “Merge pull request” button and second_branch merges into main automatically — since there were no conflicting changes. After, our main branch app.sh will have “echo ‘Hello World from second branch!’”.
Let’s now click the green “Compare & pull request” button for the third_branch prompt we see on our GitHub page. Now instead of the green “Able to merge.” message we are used to — we will see the red “Can’t automatically merge” message:
We should not create a pull request if GitHub cannot automatically merge our branch. Instead, we should resolve our merge conflict in third_branch in out local repository and then push our changes to GitHub after. What this means is — we should update our third_branch with the latest changes from the main branch and then push the resulting third_branch up to GitHub. This updated third_branch will be able to automatically merge with main.
Above you will see I started on the third_branch. From there I run “git pull origin main” — which means go to the GitHub repository online and pull the changes on the main branch into the current branch. If you look at the green message in parentheses in my git bash — it changed from “(third_branch)” to “(third_branch *+|MERGING)” because we are now merging main into third_branch locally instead of on GitHub. Running “git status” will show us the conflicting files in our merge, but in this case the only conflicting file is app.sh. Let’s look inside app.sh to see what the conflict is:
As you can see above, git automatically put all of the conflicting changes into our file. Between “<<<<<<< HEAD” and “||||||| fd0f83b” you can see the changes from third_branch. Between “||||||| fd0f83b” and “=======” you can see the original state of the third_branch when it originally branched from main. Lastly, between “=======” and “>>>>>>> 6126...” you can see the current state of the main branch.
Git doesn’t know which change is correct and this is why it can’t automatically merge our code for us. Git shows us all the changes together so we can decide for ourselves which changes to keep. So I’ll delete everything besides the latest changes from third_branch:
Now that we have resolved the merge conflict, we can git add, git commit, and git push our manually merged code:
Pushing third_branch to GitHub prompts us with the “Compare & pull request” button which we will click:
After opening the new pull request between third_branch and main we see the green “Able to merge” message because our conflicts are now resolved:
We can click the “Create pull request” button. On the pull request page we can click “Merge pull request” and our changes will automatically merge to main. Now that we have merged our pull request, we can go back to our terminal/git bash and sync the local repository’s main branch with the online repository:
After getting through the first four steps we can go back to GitHub and click on the “commits” toolbar option and we will see this:
Here we can see all the commits on the main branch and we can switch to other branches to see their commits. When learning about using Git and GitHub for collaboration — it’s important to understand how the history of the project evolves over time. I encourage you to look into each of the “Merge pull request” commits to see how merging a pull request changes the history of the project.
Another useful page to look at on GitHub is the Branches Page you can get to by clicking the “branches” toolbar option from your GitHub repository’s main page. Here we can see all the branches we have pushed to GitHub — and you’ll notice that all of them have been merged at this point. Usually after we merge a branch we can delete that branch by clicking the red garbage can icon seen below.
Thanks for reading! I’d love to hear your feedback or take any questions you have, so please comment below and I’ll try my best to help.