Archive for the ‘Uncategorized’ Category

Git Reset, Revert, Merge Conflicts and the Case Of The Faulty Merge

Git, as we know is a fast, open source, distributed version control system that is quickly replacing subversion in open source and corporate programming communities. As a developer, many a times i have been amazed by the power of git and how it takes care of our code repo. It track files in the project, we periodically commit the state of the project when we want a saved point. The history of our project is shared with other developers for collaboration, merge between their work and ours, and compare or revert to previous versions of the project or individual files.

As mentioned earlier, Git, at a fast pace, is replacing subversion in open source and corporate programming communities. Hence most open source developers would have had a taste of git and its power. We all would have done a git init, push, pull, rebase and stuff in our day to day programming activity and those would be quite trivial to most developers.

However there are certain facets of git(merges, conflicts, reverts and such) which does create some kind of confusion to developers, at least when they use it for the first time. What made me write down this post is an incident that happened to my colleague while he was on work. Will get into that shortly.  Before  getting into that, let me just stitch in a brief on Revert and Reset in git.

Revert and Reset

Git provides us multiple methods for fixing up mistakes while in development mode. This is important, because it saves not just our work but the others who are involved in the same project.

If you have actually done a mess with your working directory, but actually haven’t committed the changes, the best way is to perhaps do a hard reset.

$ git reset --hard HEAD

This would just wipe off the changes that you have made in your git index and also any outstanding changes that you have made in your repo.

Now suppose you have committed your changes, but haven’t pushed it into master,  and then suddenly you feel like you shoudn’t have made the previous commit(or a sequence of your previous commits), you could again reset hard. This is as simple as doing

$ git reset --hard HEAD~n

This would set the HEAD of the git index to ‘n’ commits prior to your current head. The problem though with doing a git reset –hard is very obvious. This is how your commit log looks like with at A its head

o  ->  o  ->  o  ->  D  ->  C  ->  B  ->  A

Suppose you do

$ git reset --hard HEAD~3

Now your commit log would be.

o  ->  o  ->  o  ->  D

This means that the changes that you made right from A to C have been vanished and you are not going to get it back. The bottom line is simple. You are not able to change the effects made by a single commit(ofcourse, the exception is your last commit as we have already seen).

git-revert is just for that.

The current commit log would look like this

o  ->  o  ->  o  ->  D  ->  C  ->  B  ->  A

At any point of time, you realize that ‘C’ is bound to break your code(hopefully it still hasn’t), you may well want to undo the changes made by C. This could be done by

$ git revert (commit id of C).

This would create a new commit that undoes the commit C. You will be given a chance to enter a new commit message, but the default message that indicates its ‘the reverse of the commit C’ would be the most indicative commit message to have.

o  ->  o  ->  o  ->  D  ->   ->  B  ->  A  ->  rC

where rC is the reverse of C.

This revert is a straightforward revert(i.e. it just undoes the data made by the commit reverted). Since all thats being talked about is a single branch, there aren’t any complications that would arise here.

Merge and reverting a faulty merge

Now let me talk about the incident that i had mentioned earlier. All these happened as a result of an accidental Merge. My friend did this

$ git pull origin experimental

while he was still sitting in his master branch. The experimental branch has now been merged into the branch master. This was totally unintentional(he never planned to do a merge). There were no merge conflicts however. The mainline code broke. We had to revert this faulty merge.

Master  ->            P   ->   x    ->  M
                                \                     /
                                   \                /
Experimental ->        A    ->   B

This would give you a picture. P is the point of branching. x is some commit made in the mainline branch totally unrelated to the side line branch. The side line branch itself has got two commits of its own, A and B. M is the merge commit (experimental has been merged with master). The code broke. Hence, we need to revert M(the merge commit).

Master  ->            P   ->   x    ->  M  -> W
                                \                     /
                                   \                /
Experimental ->        A    ->   B

Now as seen, the merge has been reverted(W is the reverse of M). This was done with

$ git revert -m 1 (Commit id of M)

This adds W to the commit log as well. Now the faulty code in the experimental branch was worked upon and fixed and its been made ready for the merge (again!). The experimental branch is now merged with the master branch. What was weird(for us, at that point of time) and noticeable was that the code changes that were made after the ‘merge revert’ appeared in the master branch whereas the ones made before the revert didn’t appear. i.e.

Master - >          P -> x -> M -> W -> x -> x -> M2

Experimental ->        A -> B  -  -  -  -  -  -  -   C -> D

Again, x are the commits unrelated to the experimental branch. M2 is the second merge. Commits in the experimental branch,C and D, fixes the faulty code in A and B. Whats to be noticed is that, after the updated experimental branch has been merged, none of the changes made by A and B would appear in the master branch, whereas the changes made in C and D would.The reason was found out soon.

Linus Torvalds explains the situation:

     Reverting a regular commit just effectively undoes what that commit
     did, and is fairly straightforward. But reverting a merge commit also
     undoes the _data_ that the commit changed, but it does absolutely
     nothing to the effects on _history_ that the merge had.

     So the merge will still exist, and it will still be seen as joining
     the two branches together, and future merges will see that merge as
     the last shared state – and the revert that reverted the merge brought
     in will not affect that at all.

Thats what just happened here. W(merge revert) undoes the data made by M(merge) but does nothing to the commit history brought in by M.There fore when the second merge,M2, is made, the commit history is checked and M is found to be ‘last shared state’. Hence, only those changes that has been made after the ‘last shared state’, M, will be merged into the master branch now(i.e. commits C and D). None of the data created in A and B would merge, because as per the commit history, they are already merged.

Solution to this problem is also explained by Linus himself. The fix is to ‘revert the revert that brought in W‘, i.e, revert W before you do in the next merge,M2.

Thus the main line commit log would be

P  ->  x  ->  M  ->  W  ->  x  ->  x  ->   ->  M2.

where Y is the reverse of W and M2 is the merge made after that.

$ git revert (commit id of W)

adds Y to the commit log. The above commit log would be equivalent to

P  ->  x  -> M  ->  x  ->  x  ->  M2

where there is no W nor a Y and then the second merge has been performed, M2. Now this would be fine, and all the changes made in the experimental branch should be seen in the master branch(ignoring merge conflicts). If there are any merge conflicts arising, git leaves the index and the working tree in a special state that gives us all the information needed to resolve the merge.

Merge Conflict

A Merge conflict would throw in the following message:

CONFLICT (content): Merge conflict in sample_script.rb Automatic merge failed; fix conflicts and then commit the result

Trying to switch to the experimental branch would give you this

error: you need to resolve your current index first

The files with conflicts will have markers upon them.

<<<<<<< HEAD:sample_script.rb "We would be starting off now" ======= "This would be the end" >>>>>>> d31f96832d54c2702914d4f605c1d641511fef13:sample_script.rb

Now we need to resolve these conflicts manually followed by adding the file and commit it.

$ git add sample_script.rb
$ git commit -a

The commit message would already be filled in indicating that its a conflict resolving commit. I always prefer not to add in anything extra on that.

gitk

It would also be helpful to have the ‘gitk’ tool when you are analyzing your commit logs, specially when you have more than once branch. You would be given a neat graphical representation of your working directory.

$ sudo apt-get install gitk

if you already don’t have one.

Image

This definitely would be helpful in getting a better picture.

Solution to ‘Wireless disabled by Hardware switch’

Ohhh … Suddenly my wifi goes off( a combination of DELL with Ubuntu natty) and got a display – wireless disabled by hardware switch. Got down to googling and finally got this.

To get back your wifi to start working, type in the following:

$:  sudo rfkill list

You will get back something like this.

0: dell-wifi: Wireless LAN
    Soft blocked: yes
    Hard blocked: no
1: dell-bluetooth: Bluetooth
    Soft blocked: no
    Hard blocked: no
2: phy0: Wireless LAN
    Soft blocked: yes
    Hard blocked: no
4: hci0: Bluetooth
    Soft blocked: no
    Hard blocked: no

As you could see (0,2) the Wireless Lan has been soft blocked.  We need to unblock it to get it up and working properly.

$: sudo rfkill unblock 0

$: sudo rfkill unblock 2

 

Restart your networking

$: sudo /etc/init.d/networking restart

 

and yup! the wifi should be back now.

Back after a Long Gap…

Haven’t Written any thing for  quite some time now. It was last november that i actually sat down to write something. Started off my professional career then and obviously was busy with work and stuff. Need to get back to writing stuff, little and bigger stuffs that i have learnt while working. In between i have fallen in love with a a new language – Ruby, the popular choice for web apps these days.  From a person who never had any kind of fondness for OOP, i have started loving to talk about about objects and classes. Learnt the difference between fun coding and professional coding. These 6-8 months has really been a learning curve for me and i really do hope that my following posts would reflect that.

Getting started with PHP and apache

Someone who gives it a thought of using PHP , apache and stuff for the first time will be faced up with a few number of fixed problems . Configuring your apache server , establishing a connection between PHP and apache , stuffs like that . Here is a basic introduction to start using these things and kick off as a web programmer .

Obviously you need to have PHP and apache installed on your system .

$ : sudo apt-get install apache2

$ : sudo apt-get install php5-cli

$: sudo apt-get install libapache2-mod-php5

 

would get you apache and PHP installed on your system  .

Using the appropriate versions is left upto individuals .

Just have a peep into some of the files like :

/etc/php5/apache2/php.ini —–> You would see a lot of variables set to ‘ON’  and ‘OFF’ . You may well have to toggle those values as and when necessary .

 

Try starting , stopping and restarting your apache web server .

$ :sudo  /etc/init.d/apache2 start

$: sudo /etc/init.d/apache2 stop

$: sudo /etc/init.d/apache2  restart

 

Once everything is fine and and perfect  , try out your first PHP script . Script it , save it in a file with a ‘.php’ extension and put your file in the directory ‘/var/www ‘. Now you could access this script from your browser

localhost/’scriptname’

and you see the result right there in front of you . Thats just how you enter the world of web programming .

GreaseMonkey : Customizing your webpages

There would have been times when you would have felt if the web page in front of you behaved a bit more according to your like . This might specially happen if the page consists of forms that you fill with data directed to live servers .  In such cases you wouldn’t mind customizing the page to suit your needs so that you don’t do some nonsense that would result in chaos .

Firefox , i see many using it as their default browser , offers a plugin called ‘Grease monkey‘  that allows you to do just that . All you need to is to install the plugin , write your own javascripts , install them ( thats pretty easy to do ) and start using them  .

Write your javascripts to customize your webpage . What you need to do in addition is to add some metadata providing extra information to greasemonkey .

The meta data might look as follows :

 

 

 

 

 

 

The first and the last lines are necessary to indicate to the greasemonkey that the script it to be processed by it .

The name and the description are optional . It might prove helpful to you if you have scripted and installed a number of greasemonkey scripts .

The 4th an the 5th line of the metadata are extremely important and needs to be well understood . These lines tell the greasemonkey the URLs on which the script is to be applied and not to be applied .

@include -> specifies the URLs on which the script is to be installed . Here ‘*’ is specified which is just a wildcard and indicates that the script is to applied on all the sites  .

@exclude -> specifies the URLs that are to be left out . It is to be noted that @exclude is processed before @include .

This gives you an idea of the metadata part of the script . Now you may write your own javascript , add your metadata at the beginning and save the file with the extension ‘ .user.js ‘  .

To install the script , open the file in firefox and you would see an option ‘install’ . Just give a click and you are ready to use your greasemonkey script .You could manage your script , disable it , uninstall it as well . Just click

Tools —-> Greasemonkey —-> Manage user scripts ….

Having another plugin ‘firebug’ may help you in the process of writing the script . This allows you to view the html code of the webpage that is infront of you . Infact the plugin is almost a necessity to help you write efficient code with greasemonkey .

Now you may start writing your own greasemonkey scripts and customize any of the webpages as and according to your like . It’s also to be understood that greasemonkey is a plugin of firefox . If you use Google chrome as your browser , you wouldn’t need to install any plugin . The facility to customize the webpage is provided by default . You may use the same code that you have written to work with greasemonkey . The metadata and the process of installing is the same and obviously the results are the same as well .

Using Screens

You might have often had the experience where you would have had to open quite a few terminals on your screen simultaneously . This might often be the case when you are doing stuffs like data processing on particular files and you intend not to sit idle during that particular time . What you do is to keep unnecessary number of terminals open on your screen .

You could get rid of this by using the ‘screens’ option in Linux . This allows you to enter a new screen where you could perform time consuming processes like a data processing operation using the  ‘awk’  command . Start the process in the screen , exit the screen and now do your own stuff in the main console , go back to your screen after a while and view the results of  whatever operations you had performed . You could do all this stuff without the necessity of opening terminals again and again .

Create a new Screen :

$ : screen -S ‘Screen name’

To detach from the current screen :

Use CTRL + a + d

To terminate a screen :

Use CTRL + d

To attach an already created screen :

$ : screen -x ‘screen name’

You could keep on creating screens within screens and keep going on as and when needed  .

Version control Systems…

Version control is a system that records changes to your files and allows to view specific versions of a file or set of files.VCS is used so that you don’t screw up your files or your entire project as a result of the silly , careless mistakes that you have made.
Many people do their own version control by copying their files to another directory.This is a quite simple and easy approach if you are careful enough so that you won’t agonize by doing something disastrous so that you may lose all your stuff later.Therefore keeping in mind that such things can happen ,after all we are all humans, we use version control systems.

Centralized VCS and Distributed VCS.
Centralized VCS
CVCS includes a single server that contains different versions of the files and the clients could check into that.The major advantage of this system is that administrators have fine grained control over whats happening ,but it has serious drawbacks as well. They are:
Single point of storage if crash would be fatal.
The clients could pull anything from the repository but they need a commit access to push something into it.This might lead to a client getting frustrated if he/she has not been granted a ‘commit access’ even after working for a longer period of time. Also there might something political issues related to administration.

Distributed VCS.
In DVCS ,you could push data into the repository with the same ease with which you could pull from it. All the repositories are at the same level and therefore we could collaborate with any of the repositories.Examples of DVCS are Git , mercurial , bazaar..etc…