Tuesday, April 1, 2014

Git Real - Level 4

Notes from Code School's Git Real Course - Level 4

Collaboration Basics

Here is a scenario in which two people are working on the same files.
For example, Jane clones the repository to her local machine. She runs:

Jane $ git clone https://github/codeschool/git-real.git

She adds two files
Jane $ git add --all

She commits her two files
Jane $ git commit -m "add two files"

And she pushes them back up to the remote repository
Jane $ git push

Great! All is good, no conflicts!

But wait, at the same time Gregg also clones the remote repository to his local machine.

Gregg $ git clone https://github/codeschool/git-real.git

Gregg also makes changes to a file (README.txt), and does an add and commit in one step.

Gregg $ git commit -am "update readme"

Now, if Gregg tries to push his updates to the remote repository, his push will be rejected!
This is because Gregg's local timeline HEAD is behind Jane's.

To solve this issue, Gregg must first do:
$ git pull (to pull the most recent version of the remote repository)

then run:
$ git push (to add his changes to the remote repository)
Success!

But what exactly is happening here? This is where we look into the mechanics under the hood.

Understanding Git Pull

$ git pull
1. This will fetch(or sync) our local repository with the remote one.
(This step is the same thing as running the $ git fetch command). Although we are fetching the remote version of the repository, it doesn't actually update our local master. Instead, the pull command actually creates a new branch on your local timeline called 'origin/master'.
pulling remote repository to origin/master branch
pulling from remote

2. Next thing the pull command will do for you is to take the new 'origin/master' branch (the one it just created) and merge it with your local master (this is the same action as if you ran $ git merge origin/master - but you don't need to because git pull does it all!). Once this is complete, it will delete the 'origin/master' branch.

3. Next it will create a new merge commit with a message that describes the merge with the remote repository. Save this from the VI editor, and you will get the success message saying that git performed a recursive merge. (Note: this part is a little ambiguous, but let's roll with it.)

If you take a look at the log, it will say there were two branches, and now there is 1.

All that with one $ git pull command, amazing! Now when Gregg runs a $ git push command, his push will be successful because he pulled down Jane's changes, merged with his own. Now he can push to remote.

A Note About Merge Commits: 

Not everyone is a fan of them. Some people think they pollute the repository and log history. If you have a lot of collaborators, you might have 10 commits, 3 to 4 of which are merge commits. It can start to get sloppy. The Git Real course will get into a way to handle this in later levels.

Merge Conflicts

Merge conflicts happen when you have two people working on the same code at the same time, in the same file. For example, Gregg updates the README.txt, but Jane updates the README.txt at the same time with different information. Jane finishes her work first, so she commits her changes and pushes them to the remote repository. Next, Gregg finishes his work, and runs a $ git pull to make sure he has the most current version of the repository. BUT, git outputs that there is a merge conflict.

Gregg runs $ git status to see the details of the conflict. The status output will show that both Gregg and Jane modified README.txt.

This conflict is within the file and so must be manually fixed. When Gregg goes into the README file, he will see his changes, as well as Jane's changes written there, plus some git markup. Gregg must remove the git markup and change the text in the file to be correct (we're assuming Gregg chooses his own text over Jane's because he's an egomaniac).

Now Gregg can run:
$ git commit -a
Leaving off a commit message because the one git provides is pretty darn good already. The message will include the file that had the conflict, and that the conflict has been resolved.
Gregg runs:
$ git push
and everything is resolved.


About this blog: This blog is an attempt to summarize my learnings as I learn them. Expect inaccuracies, incompleteness and inconsistencies.

No comments:

Post a Comment