GIT

GIT HAND BOOK

GIT CONFIGURATION

There are three levels of configuration in GIT

1. Local - local repo

2. Global - Global

3. System – System level configuration

cat ~/.gitconfig

Avoid carriage return issues

Windows – git config –global core.autocrlf true

Linux/Mac - git config –global core.autocrlf input

Setting Alias

git config –global alias.s “status –s”

git config --global alias.lg "log --oneline --all --graph --decorate"

GIT STORING MACHINISM

Git storing mechanism is different from SVN.

SVN thinks of the information they keep as a set of files and the changes made to each file over time.

Git thinks of its data more like a set of snapshots of a miniature file system. Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. To be efficient, if files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored. Git thinks about its data more like a stream of snapshots.

Git doesn’t store data as a series of changesets or differences, but instead as a series of snapshots

GIT STATES

Git has three main states that your files can reside in: committed, modified, and staged.

Commited - safely stored in local db

Modified - Changed the file by not commited

Staged - Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

GIT directory, Working directory, Staging area.

The Git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.

The working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.

The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes reffered to as the “index”, but it’s also common to refer to it as the staging area.

The basic Git workflow goes something like this:

1. You modify files in your working directory.

2. You stage the files, adding snapshots of them to your staging area.

3. You do a commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory.

Initializing Repository

git init - This creates a new subdirectory named .git that contains all of your necessary repository files – a Git repository skeleton

git add - ADDS THE FILE

git commit -m "Message for the commit"

Adding Remote Repository

To add remote repository use git remote add origin. Here origin is the alias used to refer the remote and can be of any name.

Rename File

Don’t make substantial commit before renaming file.

If you have renamed a file and check for status, git will identify it as one file deleted and one file added. But if you say git add, this will automatically detect that the file is changed and renames it GIT could think contents are different and file name is different so, this could be a new file added – Hence NO substantial change while doing renaming of file.

With the same token – Don’t try to remove one file in one location and add another file in different location which is similar(though it is different file) in the same commit. GIT may think that you might have renamed it.

GIT Internal- How GIT does this is – it has run the content of both the files and check the similarity index. Similarity index is a decimal between 0 to 1. 0 is different and 1 is char to char identical. By default similarity index exceed .5 then GIT marks this as file rename. This is the reason why there should not be substantial change in file in the same commit while renaming.

Deleting a FILE

File can be deleted either through git or through file system. If you are removing file through git command use ‘git rm <filename>’ this deletes the files and puts it in the stage directory. When you remove the file through IDE or finder then when you check the status of the git it would show the deleted files in unstaged state. You can add then commit for the changes to take effect.

Ignoring Files

If there are log files or ide related files which you do not want to be tracked, create a .gitignore file and list all the file which you don’t want to track.

While doing this there could be couple of interesting

1. After adding .gitignore, git will not show your log files in the tracking list, but it will show .gitignore file as untracked file. This is becase the .gitignore will be used by other persons who are working on this repository as well. Hence we might need to add and commit our .gitignore file.

There is another way of doing it by using global ignore file.

git config --global core.excludesfile ~/.gitignore

You can have as many gitignore file as you want, but it is not a good idea. But try to have a single file which list all the files to be ignored.

But if you want to ignore the files only locally – add the excluded files to “ .git/info/exclude” file.

If you want to track one special log file add ‘!special.log’ in the .gitignore file.

ShortCut for Add and Commit

You can add and commit at the same time using

git commit –am “Commit message”. But this will not work for untracked files.

BRANCHING

Purpose of a branch is to create a independent line of work.

Create a feature branch for every new feature

MERGING

There are 2 kinds of merge.

1. Fast Forward Merge

2. Recursive

Fast Forward Merge – When there are no difference in history only then fast forward merge is possible.

i.e when you create new branch and there are no commits in the master and the commits only happen in the new branch. When you merge such branch it will be merged as fast forward merge.

This will create linear history as if the changes were done on master.

Forcing recursive merge:- To over this while merging use –-no-ff command while merging. This will create a new commit and the log history will show the details of the branch merged.

“git merge --no-ff <new branch>

Recursive Merge – Bring 2 different histories together. Which creates new commit which brings them together.

Rule of thumb – when there are 2 or more branches with some commits, it has to be recursive merge.

Recursive merge give us more information about which branch the unit of work was made.

FETCH VS PULL

Pull is fetch + merge

Fetch only fetches the origin/branch which need to be merged

git pull --rebase

pull rebase to true can be set in config

git config --global branch.autosetuprebase always

Merging Vs Rebasing

When getting the latest codes from the remote

git pull --rebase

Does a fetch and rebase. You can set pull

Spurious merge commits.

Say, you want to get all the changes made in ‘dev’ branch to the ‘feature1’ branch. In this case, you have 2 options

1. By merging master to dev ‘git merge feature1

2. By rebasing master.

a. git checkout feature1

b. git rebase dev

This will merge all the commits from master by rebasing. How it works is that, it will find the common ancestor of the two branches, getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change after ‘dev’ merge changes are merged into ‘feature1’.

Config for Setting diff tool

git mergetool -t kdiff3

git config --global merge.tool kdiff3

git config --global mergetool.kdiff3.path /Applications/kdiff3.app/Contents/MacOS/kdiff3

GIT UNDO

git reset – throws away commits – 3 stage of reset

git reset --soft –mixed –hard

git reset HEAD~2 ( resets last 2 commits)

Adding --soft will leave the files in the staging areas so it can be added again

--hard will throw away all your work away

--mixed will clear the staging area and leave the files(this is the default mode)

REFLOG

git reflog

Keeps track of all the changes for last 30 month. Same laptop and have not done a Garbage collection.

DELETING REMOTE BRANCH

git push origin --delete <branchName> or

git push origin :<branchName>

GIT UNDO

To amend only the last commit comment

git commit --amend

git show <hash>

Git amend also will help in adding file to the earlier commit.

GIT RESET

git reset HEAD~1 - Removes laste commit

git reset --mixed is the default and will remove the commit and leave the files.

git reset --soft will leave the files in the staging area

git reset --hard completely throws away the changes and deletes the files.

Even if you done a hard reset you can get back the commit if you know the hash of the commit by issuing

git reset --hard <hash> but you will loose other commits done after that

git cherry-pick <hash> will get only the commit

You can also do by creating branch from reflog

git checkout <hash> and git checkout –b <branchname> -- This will have all the commits from the hash.

TAGGING

Normally used to mark release points

git tag -- list the tags in alphabetical order

Git uses two main types of tags: lightweight and annotated.

A lightweight tag is very much like a branch that doesn’t change – it’s just a pointer to a specific commit.

Annotated tags, however, are stored as full objects in the Git database.

They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed. It’s generally recommended that you create annotated tags so you can have all this information

git tag -a v1.1 -m "Tag Messages" - Annotating TAG

git show v1.1 - shows tagging details

git tag v1.1 -- Light weighted tag

git tag -a v1.1 8deec10 - Specify the hash name to tag - this can be used if you forgot to tag a release and there were few more commits added after the release

GIT DOES NOT PUSH TAGS by default

git push origin [tagname] to push tags to remote

git push origin --tags - Push all tags to remote

You can’t really check out a tag in Git. But you can put in branch which looks like a specific tag

git checkout -b version2 v2.0.0