GIT Overview – Reviewing history – git log



GIT Overview – Reviewing history – git log

0 1


jcruzmartini.github.io

Slides for Git webcast based on http://patok.github.io/git-intro

On Github jcruzmartini / jcruzmartini.github.io

GIT Overview

CONTENT

  • Introduction
  • Basic Operations
  • Branching & merging
  • Remote Repositories
  • References
  • Examples

What is git?

  • it's an open source version control system
  • goals: speed, simple design, strong support for non-linear development (thousands of parallel branches), fully distributed, able to handle large projects like the Linux kernel efficiently (speed and data size)
  • developed as a version control system for Linux in 2005
  • created by Linus Torvalds (who also created the Linux kernel)

! another definition: stupid content tracker

SCM Taxonomies

Storage:

  • diffs/deltas
  • DAG/snapshots

SCM Taxonomies

Deltas vs Snapshots

SCM Taxonomies

By architecture

local: restricted to a local machine centralized: client-server distributed: pair networks, there are multiple in-sync copies

SCM Taxonomies

Taxonomy matrix

Features

local operations (local repository copy, no need to be online): checkouts, commits, branching, history analysis integrity: each object in the database has a hash (SHA1 - 40 hexadecimal digits - criptographycally safe) simple storage structure: always writes data, no updates 3-status files: committed, modified and staged (ready to be committed)

File Statuses

Basic Commands

Initializing a repository

  • local initialization

    $ git init

  • clone a remote repository

    $ git clone git://github.com/schacon/grit.git

.git directory

$ tree .git
    .git
    |-- config
    |-- description
    |-- HEAD
    |-- hooks
    |   |-- commit-msg.sample
    |-- index
    |-- info
    |   `-- exclude
    |-- objects
    |   |-- info
    |   `-- pack
    `-- refs
        |-- heads
        `-- tags

Checking the status

nothing to commit

$ git status
    # On branch master
    nothing to commit (working directory clean)

Checking the status

There are modifications

    $ 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)

			

Adding new files

    $ git add README

    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #   new file:   README
    #
			

Staging modifications

    $ 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
    # 
			

Ignoring changes (.gitignore)

$ cat .gitignore 
    *target/
    *.settings/
    *.classpath
    *.project
    *bin/

# a comment - this is ignored
    *.a       # no .a files
    !lib.a    # but do track lib.a, even though you're ignoring .a files above
    /TODO     # only ignore the root TODO file, not subdir/TODO
    build/    # ignore all files in the build/ directory
    doc/*.txt # ignore doc/notes.txt, but not doc/server/arch.txt

Looking at changes in detail

$ 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 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

Looking at changes (staged or cached)

$ 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

Committing changes

$ 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

Deleting

$ git rm grit.gemspec
    rm 'grit.gemspec'
    $ git status
    # On branch master
    #
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       deleted:    grit.gemspec
    #

Renaming or moving

$ git mv README.txt README
    $ git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 1 commit.
    #
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       renamed:    README.txt -> README
    #

git is smart enough to detect it when it was not informed

$ mv README.txt README
    $ git rm README.txt
    $ git add README

Undoing the last commit: commit --amend

$ git commit -m 'initial commit'
    $ git add forgotten_file
    $ git commit --amend

Undoing changes: reset

Let's suppose...

$ git add .
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   README.txt
    #       modified:   benchmarks.rb
    #

... and then we want to go back and not to commit benchmarks.rb

$ git reset HEAD benchmarks.rb
    benchmarks.rb: locally modified

    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   README.txt
    #
    # Changed but not updated:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   benchmarks.rb
    #

Reviewing history

git log

$ git log
    commit ca82a6dff817ec66f44342007202690a93763949
    Author: Scott Chacon <schacon@gee-mail.com>
    Date:   Mon Mar 17 21:52:11 2008 -0700

        changed the version number

    commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
    Author: Scott Chacon <schacon@gee-mail.com>
    Date:   Sat Mar 15 16:40:33 2008 -0700

        removed unnecessary test code

    commit a11bef06a3f659402fe7563abf99ad00de2209e6
    Author: Scott Chacon <schacon@gee-mail.com>
    Date:   Sat Mar 15 10:31:28 2008 -0700

        first commit
			</schacon@gee-mail.com></schacon@gee-mail.com></schacon@gee-mail.com>

other alternatives to format the ouput:

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

 Rakefile |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

 lib/simplegit.rb |    5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

 README           |    6 ++++++
 Rakefile         |   23 +++++++++++++++++++++++
 lib/simplegit.rb |   25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)
			</schacon@gee-mail.com></schacon@gee-mail.com></schacon@gee-mail.com>

shows files and changes statictics

other alternatives to format the ouput:

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,5 +5,5 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end
\ No newline at end of file

			</schacon@gee-mail.com></schacon@gee-mail.com>

shows diffs between commits, for the last two commits!

Reviewing history

... visual ;-)

Saving the work in progress

Using the stash

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#

$ git stash save
Saved working directory and index state \
  "WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")

Using the stash

$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log

$ git stash apply
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   index.html
#      modified:   lib/simplegit.rb
#

Getting help

Help!

$ git help
usage: git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [-c name=value] [--help]
           <command></command> [<args>]

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and merge with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

See 'git help <command></command>' for more information on a specific command.

			</args></name></path></path></path>

$ git help status
$ git help commit

Branching

What is a branch in Git?

A branch in Git is an agile and movable pointer to a commit. When you create a repository, Git makes a branch that "points" to the last commit. By default has the name of "master". You can create your own branches, from any commit. As you make new commits, that pointer is going to move forward automatically.

Simple Branching

A scenario example:

we are working in a project that we have somes commits already we begin to work in a new story and we create a new branch call "iss53" it comes a requirement to solve a high priority bug need to momentarily leave the story to provide a hotfix we create a branch "hotfix", and once we test our fix, must be merge and needs to be deployed in production back to work in the story

History of the current project

New branch iss53

$ git checkout -b iss53
    Switched to a new branch "iss53"

Commits of the iss53 branch

$ vim index.html
    $ git commit -a -m 'added a new footer [issue 53]'

watch how the reference is move forward

Back to master to work in the fix

$ git checkout master
    Switched to branch "master"

Git resets your working directory to be the same that the last commit on master.

Create the hotfix branch, and we build the fix

$ git checkout -b 'hotfix'
Switched to a new branch "hotfix"
    
    
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix]: created 3a0874c: "fixed the broken email address"
1 files changed, 0 insertions(+), 1 deletions(-)

Ready to merge the hotfix into master

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast forward
README |    1 -
1 files changed, 0 insertions(+), 1 deletions(-)

Ready to deploy in production and get back to the story!

Fast forwarding branches

A branch that was updated recently by commits, is likely to make fast-forwarding when your commits are ancestors of the new ones.

Back to the story

removing the hotfix branch

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

switch to 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(-)

Merging

How can I update master with the new functionality?

$ git checkout master
$ git merge iss53
Merge made by recursive.
 README |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

Merging: trouble case

Git will let you know when cannot merge automatically

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

$ git status
index.html: needs merge
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   unmerged:   index.html
#

<<<<<<< HEAD
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
  please contact us at support@github.com
</div>
>>>>>>> iss53

Merging: trouble case

Must be resolved manually or using some merge tool (mergetool)

$ vim index.html

$ git add index.html

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

Getting branch information

Some useful commands

$ git branch -v
iss53   93b412c fix javascript issue
* master  7a98805 Merge branch 'iss53'
testing 782fd34 add scott to the author list in the readmes

to get local branches

$ git branch --merged
iss53
* master

Informs the branches that are merge in the current branch

$ git branch --contains e5c2d6ec
* master

prints the branches that has e5c2d6ec commit on...

Branches: common strategies

Branches long stay

Very long life

Branches: common strategies

Branches by topic

Topic branches on the other hand has very short life

Rebasing vs Merge

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

gets the C3 commit and replicates in the branch generated by the new C3 commit

Remotes repositories

The remotes repositories allows you shared the code, are copies of our objects, to_synchronize_uses:

push, fetch (pull)

Showing remote repos (remote -v)

$ git remote -v
origin  git://github.com/schacon/ticgit.git

Adding remote repo (remote add)

$ git remote
origin
$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin  git://github.com/schacon/ticgit.git
pb  git://github.com/paulboone/ticgit.git

Synchronizing local copy of remote repo (fetch)

$ git fetch pb
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (41/41), done.
remote: Total 44 (delta 24), reused 1 (delta 0)
Unpacking objects: 100% (44/44), done.
From git://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit

Pushing/uploading changes in remote repo (push)

$ git push origin master

Remote repo information (remote show)

$ git remote show origin
* remote origin
  URL: git://github.com/schacon/ticgit.git
  Remote branch merged with 'git pull' while on branch master
    master
  Tracked remote branches
    master
    ticgit

Remote Repositories

Examples

Examples

To sum up

Conclusion

  • fast and efficient (most used operations are local)
  • everyone has a copy, hence there are many backups ;)
  • not need to be connected to:
    • see file history
    • create a new branch or switching branches
    • merge code between branches
    • code commits
    • see differences between versions
    • get any version of a file

References

Books

Downloads, websites

Videos