This work is a derivate of Pro Git book by Scott Chacon and Ben Straub and published by Apress. All content is licensed under the Creative Commons Attribution Non Commercial Share Alike 3.0 license.
User 'git config' to set/get config properties.
git config --systemgit config --globalgit config
$ git config --global user.name "John Doe"
$ git config --global user.email "johndoe@example.com"
$ git config --global core.editor emacs
$ git config --global merge.tool vimdiff
$ git config --list
user.name=Omair Sajid
user.email=omair.sajid@confiz.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
$ git config user.name
Omair Sajid
$ git help
$ git <verb> --help
$ man git-<verb>
$ git help config
$ git init
$ git add README
$ git commit -m 'initial project version'
$ git clone git://github.com/schacon/grit.git
$ git clone git://github.com/schacon/grit.git mygrit
A git project has three main sections. Git directory, the working directory, and the staging area.
$ git status
# On branch master
nothing to commit (working directory clean)
$ vim README
$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# README
nothing added to commit but untracked files present (use "git add" to track)
$ git add README
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: benchmarks.rb
#
$ git add benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
#
$ vim benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: benchmarks.rb
#
Now benchmarks.rb is listed as both staged and unstaged
$ git add benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# new file: README
# modified: benchmarks.rb
#
$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 3cb747f..da65585 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -36,6 +36,10 @@ def main
@commit.parents[0].parents[0].parents[0]
end
+ run_code(x, 'commits 1') do
+ git.commits.size
+ end
+
run_code(x, 'commits 2') do
log = git.commits('master', 15)
log.size
$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README2
@@ -0,0 +1,5 @@
+grit
+ by Tom Preston-Werner, Chris Wanstrath
+ http://github.com/mojombo/grit
+
+Grit is a Ruby library for extracting information from a Git repository
$ git commit
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
~
~
".git/COMMIT_EDITMSG" 10L, 283C
This is header
Commit message should have a subject (first line) a blank line and then details.
This way different tools can generate better nofications. E.g. if an email
notificaiton is gerneated then first line will used as subject of email and rest as
email body.
You should also refer your jira/redmine task in comment. E.g. Fixes Ticket #1234.
This will automatically (if configured )add a comment to your jira/redmine task referencing this commit.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
~
~
".git/COMMIT_EDITMSG" 10L, 283C
$ git commit -m "Story #182: Fix benchmarks for speed"
[master]: created 463dc4f: "Fix benchmarks for speed"
2 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 README
$ git reset HEAD benchmarks.rb
benchmarks.rb: locally modified
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README.txt
#
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: benchmarks.rb
$ git checkout -- benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README.txt
#
Listing remotes
$ git remote
Adding remotes$ git remote add <name> <path-to-repo>
Deleting remotes$ git remote rm <path-to-repo>
Conceptually, a single commit looks something like.
After couple of commits.
A branch is simple a pointer to one of these commits.
A branch in Git is in actuality a simple file that contains the 40 character SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. Creating a new branch is as quick and simple as writing 41 bytes to a file (40 characters and a newline).
Creating a new branch creates a new pointer at the same commit you're currently on.
$ git branch testing
To keep track of branch we are currently on. Git uses a special pointer called HEAD (The git branch command only created a new branch — it didn’t switch to that branch )
To switch to an existing branch, you run the git checkout command
$ git checkout testing
Let's do a commit
$ vim test.rb
$ git commit -a -m 'made a change'
Notice that only testing branch (pointer) has move forward. But master branch still points to the commit you were on when you ran git checkout to switch branches.
Now switching to master branch will move the HEAD pointer to master branch, and will revert files in working directory to the snapshot master poitns to.
$ git checkout master
Doing another commit now will move master branch forward
$ vim test.rb
$ git add test.rb
$ git commit -m "...."
Consider a repository with three branches as in figure below
Fast Forward Merge: Let's first merge hotfix into master
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast forward
README | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
As hotfix branch is merged into master so we will get rid of hotfix branch now
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
Continue work on iss53 branch
$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m ’finished the new footer [issue 53]’
[iss53]: created ad82d7a: "finished the new footer [issue 53]"
1 files changed, 1 insertions(+), 0 deletions(-)
Three-way merge: Time to merge iss53 into master
$ git checkout master
[master *]$ git merge iss53
Merge made by recursive.
README | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Git automatically identifies the best common-ancestor merge base for branch merging. It then creates a new snapshot by doing a three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit and is special in that it has more than one parent.
Occasionally, this process doesn’t go smoothly. Git will not always be able to merge files cleanly. E.g. If our fix for issue #53 modified the same part of a file as the hotfix, we’ll get a merge conflict that looks something like this:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Running git status now will show us somthing like
[master*]$ git status
index.html: needs merge
# On branch master
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# unmerged: index.html
We can now open the file and resolve conflicts. File with conflicts will contain section that will look something like
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> ss53:index.html
How we resolve conflict is upsto us. We can choese either side or merge the contents from both. E.g. in this case we can resolve conflict as
<div id="footer">
please contact us at email.support@github.com
</div>
After resolving conflict use git add to add file to staging area and then commit code to complete merge prcess.
To create new branch
$ git branch testing
$ git checkout testing
Or use shortcut to create and switch to new branch with one command
$ git checkout -b testing
To list branches (* indicates current branch)
$ git branch
iss53
* master
testing
To delete a branch
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
To view list of branches that have been merged into current branch. Branches without * have already been merged into current branch and can be safely deleted.
$ git branch --merged
iss53
* master
To see all the branches that contain work you haven’t yet merged in
$ git branch --no-merged
testing
Trying to delete this branch will give error. In case you want to force deletion then use -D instead of -d
$ git branch -d testing
error: The branch ’testing’ is not an ancestor of your current HEAD.
To push branch to remote server. (This will push local serverfix and create a new serverfix branch on remote server.)
$ git push origin serverfix:serverfix
Counting objects: 20, done.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 1.74 KiB, done.
Total 15 (delta 5), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new branch] serverfix -> serverfix
To push branch with a different name (This will push local serverfix branch as remote newname branch)
$ git push origin serverfix:newname
Pulling a new branch from server is two step process.
$ git fetch origin
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
From git@github.com:schacon/simplegit
* [new branch] serverfix -> origin/serverfix
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"
To delete a remote branch.
$ git push origin :serverfix
To git@github.com:schacon/simplegit.git
- [deleted] serverfix
Recall that to create new branch we used git push [remotename] [localbranch]:[remotebranch]. For deleting remote branch we are leaving out local branch name. This is similar to saying take nothing from local repo and push to remote.
Tags are simple pointers to commits, and they are incredibly useful for bookmarking important revisions like releases. The git tag command can be used to create a new tag
$ git tag -a v1.0 -m "Stable release"
and to list existing tags use
$ git tag
Git also lets you use git checkout with tags and commit IDs, but doing so puts you in a detached HEAD state. This means that you’re not on a branch anymore—you’re directly viewing a commit. This means that you’ll lose all your work as soon as you switch back to a real branch. To create a new branch in a detached HEAD state:
$ git checkout -b <new-branch-name>
After this we will have a new branch reference pointing to formerly detached HEAD