Thursday, December 4, 2014

Using Git

Basic tasks that you'll need to do with Git:
  • Setting up Git on your (Windows) machine. [ git config ]
  • Initializing a Git repository (local). [ git init ]
  • Saving your changes. [ git add, git commit ]
  • Inspecting a repository. [git status, git log]
  • Viewing old commits [ git checkout ]
  • Undoing changes [git revert, git reset, git clean]
  • Rewriting History [git commit --amend, git rebase]
  • Collaboration [git remote, git fetch, git pull, git push]
Download git for windows: http://git-scm.com/download/win

Now you need to configure your git installation.

git config --global user.name <name>
git config --global user.email <email>

Initializing git repository:

Open Git bash inside the preferred directory.

git init

This initializes your local repository.

Suppose you have a project MyProject. You create a directory e:\MyProject for this project.

Now you should cd to that folder in Bash and

git init

Now you have added a file MyFirstFile.java inside the MyProject folder. You add this file to staging area using 

git add MyFirstFile.java

At this time if you want to see what has been staged (or modified and not staged) until now in the current branch, use

git status

It will list the file MyFirstFile.java for this case as it has not yet been committed.

If you have more new files to add, just type

git add .

Now this file has been staged to be comitted.

You can commit this change to the project using

git commit -m "Added a new file MyFirstFile.java"

The -m flag is a shortcut to include a message with the commit. If -m is not used, you will be presented with a vim editor to edit the message and then save it to commit the changes.

If you want to display committed snapshots, use

git log

or use the 

git log --oneline

command to see only a part of the messages attached to each commit.

git checkout 

The git checkout command serves three distinct functions: checking out files, checking out commits, and checking out branches. Checking out a commit makes the entire working directory match that commit. This can be used to view an old state of your project without altering your current state in any way. Checking out a file lets you see an old version of that particular file, leaving the rest of your working directory untouched.

Suppose that we want to add a new feature FeatureA to the project MyProject.

We'll do

git checkout -b FeatureA master

to add a new branch called FeatureA separated from the master branch at last commit.

We can now commit changes to this feature and then later can merge this feature with the master branch or rebase it to some specified commit location.

How to merge?

We want to merge FeatureA with master branch, we'll:

git checkout master
git merge FeatureA

The merge can be "fast-forward merge" or "three-way merge". 


How to rebase?

We want to rebase FeatureA on master branch's latest commit, we'll:

git checkout FeatureA
git rebase master

And now the head of master is the latest commit of FeatureA.

We can now fast-forward master to point to the new head (last commit of FeatureA) by:

git checkout master
git merge FeatureA


Let's suppose you just commited a new change and you just realized that you've missed a file file2.java. You need to:

git add file2.java
git commit --amend

and then it asks you for a new message (the old commit will be deleted and a new commit with the included new file will be placed there) for this new commit. You can use --no-edit flag

git commit --amend --no-edit

if you don't want to enter a new message and prefer to use the old one instead,

git revert, git reset, git clean

Suppose that you have commited 4 changes to the MyProject repository. Now you want to undo what commit 2 has introduced to the project. You can

git revert <commit>

What happens now is that git does not delete commit2 from the history but instead it figure outs a way to undo what commit2 has done and adds a new commit to the project to reflect the changes done. (commit3 and commit4 remain unchanged). commit5 is the current project but with the changes made by commit2 undone. commit5 has the same snapshot as commit1 which was before commit2 was submitted. (You did some wild experiment during commits 2,  3 and 4 which failed miserably. Now you need to go back to commit1 and continue so you just use the git revert feature).


git revert is "safe". You can't lose your code. But you sometimes want the entire commit to be actually deleted. In this case you use 

git reset

 It unstages all files without overwriting any changes giving you the opportunity to re-build the staged snapshot from scratch.

git reset --hard

Resets the staging area and working directory to match the state of the most recent commit. Every change you have done after the last commit will be deleted (new files, changes to existing files).

git reset command can be used as

git reset HEAD~3

this rewinds the master branch to get rid of those last three commits.

The git clean command is often executed in conjunction with git reset --hard. Remember that resetting only affects tracked files, so a separate command is required for cleaning up untracked ones. Combined, these two commands let you return the working directory to the exact state of a particular commit. (e.g. suppose that you compiled a C++ source code that generated an exe file). This exe file has not been tracked so git has not touched this even with --hard option in reset command. To make the working directory exactly like the previous state, you must use git clean to delete that exe file.


Collaboration Using git

[ git remote, git fetch, git pull, git push]

git remote add <name> <url>

git remote command lets you create, view, and delete connections to other repositories. These are like bookmarks into other repos. They are just names that can be used to reference the URL in other commands like

git clone <name>

This works if you have a URL associated with <name> using remote option.

git fetch <remote>

Use this to fetch all of the branches from the repository. This also downloads all of the required commits and files from the other repository. Fetching is done when you want to see what everybody else has been working on. It is represented as a remote branch and has no effect of your local development work.

How to list all the remote branches?

git branch -r

Now you can merge this branch with the master branch using

git checkout master
git merge origin/master

git pull command

This command is used to merge upstream changes into your local repository. This is like

git fetch

followed by

git merge

Usage:

git pull <remote>

This fetches the specified remote's copy of the current branch and immediately merges it into the local copy. You can also use rebasing with pull

git pull --rebase <remote>

This is same as the previous command, but it uses git rebase instead of git merge.

git push command

git push <remote> <branch>

This will push the specified branch to <remote> along with all of the necessary commits and internal objects. This creates a local branch in the destination repository To prevent you from overwriting commits, Git won't let you push when it results in a non-fast-forward merge in the destination repository.

Useful links:

2 comments: