Git and GitHub | Part 2

Git and GitHub | Part 2

Complete tutorial on some advance stuffs like Branches, Pull request, Merge conflicts, Squashing, Rebase and more

Introduction

Welcome back ! In case you haven’t seen part-1 of the Git and GitHub blog, please read it once because it is a bit advanced topic and complete beginners may feel some difficulties in understanding part 2 directly.

So, we were in the scenario where we needed to build a news portal from different places and we successfully collaborated with each other by the techniques of pull request, merge and fork concepts. But there are still many things to know when collaborating.

Let us think of one scenario. Say, you are trying to do a matrix problem in mathematics. So, I assume you first try to solve that problem in a rough notebook and if the answer gets satisfying, you write the solution properly in a math notebook.

Git Branch

The concept of branch is similar to the above scenario. Git Branch: All the code that is not finalised must be on a separate branch. So, the main branch is not affected.

Branches allow you to develop features, fix bugs, or safely experiment with new ideas in a contained area of your repository.

You may have seen master and main branch in our previous blog alot. After you create a git repository for the very first time by cloning it from a remote server , the repository has a default branch. The default branch is a master branch. “Master” is just a naming convention of the default branch. Is it different from the main branch? This is just a change of words. The default branch name changed from “master" to “main". You can still create a branch named “master".

It is always a good practice to create different branches and work until you get your work finalised. Do Not directly commit to the main branch.

Let’s work on a branch.

Branch Demonstration

As in the figure, master/main is the default branch in a git. c0, c1, c2 are commits. The (*) is the notation for the current branch. This is also known as HEAD.

HEAD: Head is a pointer which says , all the new commits will be added on the HEAD.

Branch workflow

Screenshot from 2022-11-08 14-50-21.png

Initially, the default branch is main/master. If you commit something new to the main branch, the branch gets increased as shown in the figure below. Screenshot from 2022-10-27 16-52-39.png

You can create a new branch with any name. To create a new branch, you have to write the following command.

git branch feature

To switch to a new branch(feature), you have to use the git checkout command.

git checkout feature

Screenshot from 2022-10-27 21-43-51.png

Now, see the (*) is pointing to a feature from main. Now HEAD points to feature. Every new commit now created will start from a feature.

Screenshot from 2022-10-27 16-53-06.png

Initially the main and feature branches were at c2. After we commit something new, new commits start from the feature. So, main is at c2 and features only moved forward to c3 and from c3 to c4.

Again we created a new branch feature2. But our HEAD is pointing to a feature so c3 is the commit from the feature.

Screenshot from 2022-10-27 16-53-50.png

c4 commit is pointed by feature and c5 is now pointed by feature2. C5 is a new commit from feature2.

Screenshot from 2022-11-08 15-05-42.png

Now switch to feature again, and commit. The new commit begins from c4 which was the last commit done in the feature branch.

Screenshot from 2022-11-08 15-07-12.png

Play branching: learngitbranching.js.org

Note: The commands used in the above demonstrations.

Screenshot from 2022-11-08 15-08-01.png

After you finish work in a feature branch, you can merge. Git merge will combine multiple sequences of commits into one unified history.

git checkout main
git merge feature

Git Pull request and Merge

Real merging of branches is done via pull request.

Suppose, you are working in a team of 100’s of devs around the world. Say, you want to add a simple feature in their central repository. For that you have to issue pull request as discussed earlier in part-1 too.

Let’s create a feature branch and create some files in it as shown in the figure.

Screenshot from 2022-10-27 21-43-51.png

push the changes in the feature branch as shown in the figure below.

Screenshot from 2022-10-27 21-44-38.png

Merge the commits of feature branches in a master branch.

Screenshot from 2022-10-27 21-45-07.png

If you see the master branch, there is only random_text.md but there are many files in the feature branch. Screenshot from 2022-10-27 21-45-59.png

If you push something in the feature branch, you can only see the changes in the feature branch. To be able to see changes of feature branches in a main branch, you have to merge the branches.

Screenshot from 2022-10-27 21-46-15.png

you can do this via pull request and merge it in a master branch. Screenshot from 2022-10-27 21-47-12.png

Removing a commit from the pull request by force pushing to it

Sometimes you may issue pull requests and later you realise the pull request was accidentally issued. As a beginner, you might panic because you don’t want your maintainer to see what you have committed along with a commit message. For this case, you can delete the commit from pull request using this technique.

Screenshot from 2022-11-08 10-31-10.png

See the previous log using

git log

Inside the logs you can see all of your changes and version history.

Screenshot from 2022-11-08 10-34-24.png

Now, reset/ delete the log. It is taught in the Part-1 of Git and GitHub tutorial.

Screenshot from 2022-11-08 10-35-09.png

After resetting , you have to force push the commit.

git push origin <branch-name> -f

Screenshot from 2022-11-08 10-35-48.png

If you go to the pull request section and see the history, your commit message and files are gone and your pull request is auto-closed.

Screenshot from 2022-11-08 10-33-01.png

TIP: Never push changes directly on the production environment.

Git Upstreams

Like the literal meaning, upstream refers to something which points to where it originated from. In the git world, upstream refers to the original repo or a branch.

Sometime you want to get updated from the central repository. Someone might have changed the contents of the project. So, you need to get updated. For that purpose you have different ways. If you don't want to code, you can just click button "fetch uptream" or "update branch" in your repository.

Screenshot from 2022-11-08 10-58-26.png

  • Next way is to use CLI

In the forked branch there are 189 commits because the forked repository is not updated. But in reality there might be more commits because in open source projects, other people also contribute to a central repository. Here, central repository is askbuddie/roadmap.

Forked Repository You can see the commit count is 189.

Screenshot from 2022-11-08 11-01-04.png

Central Repository The commit count is 240 which is way ahead of forked repository which is not updated.

Screenshot from 2022-11-08 11-00-29.png

Using Command Line Interface First of all you need to add the ssh url of the remote repository.

git remote add upstream <SSH-URL>
// checkout the main branch
git checkout main
git fetch --all --prune
Git reset --hard/upstream/main

See 241 commits. It is fetched using CLI.

Screenshot from 2022-11-08 11-27-29.png

git fetch --prune is the best utility for cleaning outdated branches. It will connect to a shared remote repository remote and fetch all remote branch refs. It will then delete remote refs that are no longer in use on the remote repository.

git reset --hard/upstream/main Resets the index and working tree. Any changes to tracked files in the working tree since are discarded. this will delete all your local changes to master

If you see logs, logs are changed. But it will not be reflected in your GitHub server because you haven’t pushed the changes.

Once you push the changes, it will get reflected in the forked repository.

git push origin main

Screenshot from 2022-11-08 11-29-34.png

You can also use git pull command to fetch everything from the central repository to your forked repository.

git pull upstream main

Squash and Rebase in Git

To "squash" in Git means to combine multiple commits into one. You can do this at any point in time (by using Git's "Interactive Rebase" feature)

Sometimes you might commit many things that can be committed once in a single commit. For example: If you have commits about file creation for 7 different files, you can represent “file created” in a single commit at last.

Let’s create 4 different files with four different commit messages as shown in the figure. Screenshot from 2022-11-08 14-01-59.png

Now you have to see the logs using the “git log” command. Copy the log of the first committed file.

git rebase -i <Hash-value>

Here, -i means interactive environment.

After you type this command, you can see the vim console opens. Initially, it will show four file names with “pick” in the front.

Screenshot from 2022-11-08 14-03-53.png

Now, you can change pick to “s” in order to squash the commits. You can squash any commits with the commit of file a.

Screenshot from 2022-11-08 14-04-49.png

Save the changes typing Esc

     :x

Now delete all the commit message. Screenshot from 2022-11-08 14-08-11.png

After deleting all the commit messages, you can create a fresh commit message on your own. Screenshot from 2022-11-08 14-08-50.png

Again type :x, you can see the rebase is successful and your commits are merged. Screenshot from 2022-11-08 14-09-19.png

Merge Conflicts

Merge conflicts occur when competing changes are made to the same line of a file, or when one person edits a file and another person deletes the same file.

Suppose, you change the line no. 5 and your friend also changed the line no.5 . Now git will get confused whose change to keep as final. Git will tell the owner, whose change to keep.

You will see merge conflict, when git is not sure whose PR to merge as both of them have changes in the same line of code.

When you try to merge any one of the PRs, you will get notified as there is a merge conflict.

To resolve merge conflicts, you can resolve it manually.

Let's create Merge conflict

Let’s create two branches with the same filename and write something inside the file. Say the file name is xyz and we write something in a line 1

First File with same name but different content

Screenshot from 2022-11-08 16-59-57.png

Second File with same name but different content

Screenshot from 2022-11-08 17-00-53.png

Issue the Pull request for getting merged as shown in the figure.

Screenshot from 2022-11-08 17-01-42.png

If you try to merge any of the files, you are likely to get a merge conflict because Git gets confused whose commit to merge as both of the changes may be important.

Merge Conflict

Screenshot from 2022-11-08 17-02-03.png

To resolve the merge conflict, you have to resolve it manually as shown in the figure.

Before resolve Screenshot from 2022-11-08 17-02-19.png

After resolve

Screenshot from 2022-11-08 17-03-25.png

If you are reading this right now or in future (after 2022 AD) by any chance, thank you so much for this. If not, I would like to thank myself for writing this Blog.

I thought of writing about Hooks and CI-CD actions, but it might be a very long blog. Hope I will write more advanced topics about Git in future, maybe Part-3.

You can comment if you feel something needs to be improved. Suggestions are appreciated.

Socials

References