Understand Git and Github

This article has been published at Function Space.

(This is just my back up copy of the thing, do check this out on FS for better experience.)

Let’s say for an upcoming contest at a school, you form a team and decide to develop a software. Everything goes fine until you guys come to a stage when two or more of teammates work on the same piece of code! If you guys are working on disjoint set of files, the problem comes when you want to integrate the two modified code together manually.

Further, how would you handle a vast code distributed over several files and people working from different geographical locations? If one of the guy messed up the code, won’t all of the other teammates also suffer? The solution is a version control system. In this article, we will discuss about one of the widely used open-source version control system called git.

This article aims to give you a visual understanding of git, which otherwise might eat up your time and effort!

As an example, let’s say you want to develop a mathematical library along with a couple of friends. To start with a simple task, you write a library function to calculate power of a variable and a use case.

First of all, you need to create a git project like this:

$ git init learngit

$ cd learngit

Next, once you are in a git repository, you start writing the initial draft of the code.

file: mymath.c

#include<stdio.h>
int x;
int MyPower(int x, int y){
    int z = x, i;
    for(i = 1; i < y; i++){
        z = z*x;
    }
    return z;
}

file: mymath.h

int MyPower(int x, int y);

file: myfunc.c

#include"mymath.h"
#include<stdio.h>
int main(){
    int x = 5, y =2;
    printf("%d power %d is %d", x, y, MyPower(x,y));
    return 0;
}

Ok, enough for the first time. Time to include more people in the project. To do so, you need to add this code to the git repo you created.But before that, you ensure that the code is in running position by:

$ gcc myfunc.c mymath.c  -o mine
$ ./mine
5 power 2 is 25

Everything looks fine till now. Time to add the code to git:

$ git add .
$ git commit -m "Importing all the code"
[master (root-commit) 53762a8] Importing all the code
4 files changed, 27 insertions(+)
 create mode 100644 mine.exe
 create mode 100644 myfunc.c
 create mode 100644 mymath.c
 create mode 100644 mymath.h

“commit” means to save your changes. First time, it creates a master branch (the main branch). But wait, soon you realize that the executable mine.exe is also on git which you didn’t want as other guys working on the project may run the code on a different architecture and hence this executable file won’t work. Here’s how you can remove this:

$ git rm -f mine.exe
rm 'mine.exe'

To move your changes to the master branch, commit your changes again:

$ git commit -a -m "Removed executable"
[master 72c6dfa] Removed executable
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 mine.exe

To verify and check whether the changes you made actually made it to git or not, check the log:

$ git log
commit 72c6dfab8c71bf295e5a570c8b45a0e495c23a80
Author: Mohit Dhingra <mohitdhingras@gmail.com>
Date:   Wed Oct 30 23:27:12 2013 +0530

    Removed executable

commit 53762a87a6980b20780725b7d5d78d16f8e6295b
Author: Mohit Dhingra <mohitdhingras@gmail.com>
Date:   Wed Oct 30 20:30:23 2013 +0530    

    Importing all the code

Now you have everything ready to work on your local computer. But how to access the same from multiple places? How would your teammates work on the same stuff. For this, you need to create a remote repository. Github is your gateway to create your own repo. Once you create your account on github, you can create the repo over there. For example, following picture shows how a repo for our project can be created.

git repo

Finally, add your files on to the remote repo too and push!

$git remote add origin https://github.com/mohitdhingra/learngitrepo.git
$ git push -u origin master
Username for 'https://github.com': mohitdhingras@gmail.com
Password for 'https://mohitdhingras@gmail.com@github.com':
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 18.47 KiB | 0 bytes/s, done.
Total 8 (delta 1), reused 0 (delta 0)
To https://github.com/mohitdhingra/learngitrepo.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

You can verify whether the files are up on the github. You should see something like this: files uploaded

Your first milestone is achieved! Now, you and your teammates can all work on the same project and play around with the code. Here is how your friend can start contributing to a repo created by you (don’t forget to add them as a contributor in github).

$ git clone http://github.com/mohitdhingra/learngitrepo
Cloning into 'learngitrepo'...
remote: Counting objects: 13, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 13 (delta 2), reused 13 (delta 2)
Unpacking objects: 100% (13/13), done.

Soon, your friend realized that the result can go out of bounds. So she decides to change the return type from int to long int and do some formatting. After doing the changes, she follows the same steps, that is, commit and then push to the remote repo.

Next time when you start working on the project you can update your system with the latest version of the code by git pull.

$ git pull 
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 1), reused 5 (delta 1)
Unpacking objects: 100% (5/5), done.
From https://github.com/mohitdhingra/learngitrepo
   72c6dfa..238eef7  master     -> origin/master
Updating 72c6dfa..238eef7
Fast-forward
 myfunc.c |  2 +-
 mymath.c | 16 +++++++---------
 mymath.h |  2 +-
 3 files changed, 9 insertions(+), 11 deletions(-)

So, in the output of the command, you see that there are some changes that have been downloaded. You can always check what was modified by git log.

$ git log
commit 238eef727113ce4eadc3b3590a443b07b103adb0
Author: Aakriti <aakriti.aakriti@gmail.com>
Date:   Sun Nov 10 16:46:56 2013 +0530

    Change return type from int to long int

commit 72c6dfab8c71bf295e5a570c8b45a0e495c23a80
Author: Mohit Dhingra <mohitdhingras@gmail.com>
Date:   Wed Oct 30 23:27:12 2013 +0530

    Removed executable

commit 53762a87a6980b20780725b7d5d78d16f8e6295b
Author: Mohit Dhingra <mohitdhingras@gmail.com>
Date:   Wed Oct 30 20:30:23 2013 +0530

    Importing all the code

To see what exactly she modified, you can use the command git show -Commit Id. Commit ID can be found from logs above.

$ git show 238eef727113ce4eadc3b3590a443b07b103adb0
commit 238eef727113ce4eadc3b3590a443b07b103adb0
Author: Aakriti <aakriti.aakriti@gmail.com>
Date:   Sun Nov 10 16:46:56 2013 +0530

    Change return type from int to long int

diff --git a/myfunc.c b/myfunc.c
index 50bef42..ef84a4c 100644
--- a/myfunc.c
+++ b/myfunc.c
@@ -4,6 +4,6 @@
 int main()
 {
     int x = 5, y =2;
-    printf("%d power %d is %d", x, y, MyPower(x,y));
+    printf("%d power %d is %ld\n", x, y, MyPower(x,y));
     return 0;
 }
diff --git a/mymath.c b/mymath.c
index f83d959..a55c7e9 100644
--- a/mymath.c
+++ b/mymath.c
@@ -1,17 +1,15 @@
 #include<stdio.h>

-int x;
-
-int MyPower(int x, int y)
+long int MyPower(int x, int y)
 {

-int z = x, i;
+    long int z = x, i;

-for(i = 1; i < y; i++)
-{
-    z = z*x;
-}
+    for(i = 1; i < y; i++)
+    {
+        z = z*x;
+    }

-return z;
+    return z;

 }
diff --git a/mymath.h b/mymath.h
index 2ea00ca..b767239 100644
--- a/mymath.h
+++ b/mymath.h
@@ -1 +1 @@
-int MyPower(int x, int y);
+long int MyPower(int x, int y);

‘-‘ indicates that the line has been removed and ‘+’ indicates that the new line was added as compared to the previous version.

Here is a timeline image to show what changes have occurred till now. timeline1

In this image, each commit point represents a snapshot of the code base where you can revert back to anytime. So, you are currently at commit 3 and to go back to commit 1, this is how you revert.

$ git reset --hard 53762a87a6980b20780725b7d5d78d16f8e6295b
HEAD is now at 53762a8 Importing all the code

HEAD is actually a pointer which shows where you are currently at. ‘–hard’ option overwrites the current code base to exactly how it looked like after first commit. To go back to the latest code, you simply do git pull.

At this point of time, you and your friend decide to extend your library. You are supposed to add the functionality for basic arithmetic operations while your friend is assigned the task of adding factorial functionality. Since you both may be working on the same file, you decide to create a branch and work parallely. You can create a branch like this:

$ git branch arithmetic

And here is how you can cross-check it:

$ git branch
  arithmetic
 * master

This shows that there are currently two branches, arithmetic and master. The symbol * shows that you are currently on master branch. Again, you can push the local branch to github and create a remote branch by:

$ git push origin arithmetic
Username for 'https://github.com': mohitdhingras@gmail.com
Password for 'https://mohitdhingras@gmail.com@github.com':
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/mohitdhingra/learngitrepo.git
 * [new branch]      arithmetic -> arithmetic

To switch to arithmetic branch, you need to run git checkout:

$ git checkout arithmetic
Switched to branch 'arithmetic'

Now you can go ahead and add the arithmetic functionality in this branch and your friend can simultaneously add factorial functionality in master branch. Once arithmetic functionality is done in the side branch, it can be merged into the master branch using git merge.

$ git merge arithmetic
Auto-merging mymath.h
CONFLICT (content): Merge conflict in mymath.h
Auto-merging mymath.c
CONFLICT (content): Merge conflict in mymath.c
Auto-merging myfunc.c
CONFLICT (content): Merge conflict in myfunc.c
Automatic merge failed; fix conflicts and then commit the result.

In this particular case, git could not auto-merge since you both worked at the same part of the common files. However, it works in most other cases. You can manually resolve the conflicts by editing the file as below:

git output:

#include"mymath.h"
#include<stdio.h>

int main()
{
    int x = 5, y =2;
    printf("%d power %d is %ld\n", x, y, MyPower(x,y));
<<<<<<< HEAD
    printf("%d factorial is %ld\n", x, MyFactorial(x));
=======
    printf("%d is %0.2f%% of %d\n", y, MyPercentage(y, x), x);
>>>>>>> arithmetic
    return 0;
}

After editing:

#include"mymath.h"
#include<stdio.h>

int main()
{
    int x = 5, y =2;
    printf("%d power %d is %ld\n", x, y, MyPower(x,y));
    printf("%d factorial is %ld\n", x, MyFactorial(x));
    printf("%d is %0.2f%% of %d\n", y, MyPercentage(y, x), x);
    return 0;
}

Finally, you can go ahead with committing the merge and pushing the changes to remote branch. Don’t forget to cross-check the logs.

$ git log
commit c4e59cac5f16c8c013442290e91d5f60c7ca587a
Merge: bed0d42 fe7e332
Author: Mohit Dhingra <mohitdhingras@gmail.com>
Date:   Sun Nov 17 19:56:23 2013 +0530

    Merge branch 'arithmetic'

So, here is how the whole process looks like in a timeline: timeline2

Getting comfortable with git might take some time initially but in the long run this will prove to be time worth spent!If you are interested to know more about how Git works internally, stay tuned as we are going to discuss it in our upcoming articles. Happy coding!

Advertisements

One thought on “Understand Git and Github

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s