Sunday, October 7, 2012

Quick Tour of Git (from a NetEng scriptor)

Reviewed the book Version Control with Git: Powerful tools and techniques for collaborative software developmentin my last post.

Here is a quick tour of how I plan to use it.

Git, for those dont know, is a distributed version control and source code management system, http://en.wikipedia.org/wiki/Git_(software). It is what Linus Torvalds developed for Linux Kernel development. The word being 'distributed' and robust, large scale. It is definitely an overkill for my humble little scripts that is worked on by myself and I with three revisions in 6 months. But hay, I am a believer of 'learn once, use many times', so if I need to use a version control system anyways, might as well be one that is as robust and scalable as Git. 

Here are some useful links: 

Here are my requirements: 

1. Most of the scripts will be developed by me in a single directory. 
2. I am going to have two branches, one main and one development. 
3. I plan to merge the dev branch into main as soon as possible. 
4. People who will develop together with me will likely have either local or ssh access to the *Nix box I am using. 

***** So let's get started: ***** 

1. Making a new directory to keep my scripts, write some dummy files for demonstration purposes: 

$mkdir netengPy
$cd netengPy
$echo 'print ("hello world")' > hello.py
$ls
$python hello.py
hello world

2. Initialize it for Git: 

$git init
Initialized empty Git repository in /Users/echou/Desktop/Version_Control_with_Git/netengPy/.git/

3. Add the file and commit (refer to documentation for more backgrounds): 

$git add hello.py
$git commit -m "Initial commit" --author="Eric Chou <ericchou@pythonicneteng.com>"
[master (root-commit) 4d23187] Initial commit
 Author: Eric Chou <ericchou@pythonicneteng.com>
 Committer: Eric Chou <echou@pythonicneteng.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 hello.py
$
$

4. Create a second development branch (main was created by default): 

$git branch dev
$git checkout dev <<< here is how you switch to the dev branch
Switched to branch 'dev'
$git branch
* dev
  master

5. Create a new file under dev branch, add and commit: 

$echo 'print("foo bar")' > foo.py
$ls
foo.py          hello.py
$python foo.py
foo bar
$git add foo.py
$git commit -m "commit foo.py to dev" --author="John Doe <john@doe.com>"
[dev 8bd4655] commit foo.py to dev
 Author: John Doe <john@doe.com>
 Committer: Eric Chou <echou@pythonicneteng.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo.py
$ls
foo.py          hello.py
$

6. Switch back to main branch and merge the new files: 

$git checkout master
Switched to branch 'master'
$git branch
  dev
* master
$ls
$git merge dev <<< here is the command to merge the dev branch
Updating 4d23187..8bd4655
Fast-forward
 foo.py |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo.py
$ls
foo.py          hello.py
$cat foo.py
print("foo bar")
$python foo.py
foo bar
$

7. At this point, I am a happy single contributor to the scripts. Here are some other quick commands that might help. 

    7a. Add multiple files:

$echo "foo" > firstFile
$echo "bar" > secondFile
$git add firstFile secondFile
$git commit -m "Add first and second file"
[master a295347] Add first and second file
 Committer: Eric Chou <echou@pythonicneteng.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 2 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 firstFile
 create mode 100644 secondFile
$
$

    7b. Finding out differences between two files: 

$git diff foo.py
diff --git a/foo.py b/foo.py
index c86843b..f681f64 100644
--- a/foo.py
+++ b/foo.py
@@ -1,3 +1,6 @@
 #!/usr/bin/env python

+# Add the addtional line
+print("hello")
+
 print("foo bar")
$

8. Steps for synchronization at the heart of collaboration: 

    8a. Create bare repository without working working directory (look at documentation for the curious):

$git clone --bare netengPy/ bareNetengPy.git
Cloning into bare repository bareNetengPy.git...
done.
$

    8b. Make your new origin remote

$
$cd netengPy/
$cat .git/config
[core]
     repositoryformatversion = 0
     filemode = true
     bare = false
     logallrefupdates = true
     ignorecase = true
$git remote add origin ../bareNetengPy.git/
$cat .git/config
[core]
     repositoryformatversion = 0
     filemode = true
     bare = false
     logallrefupdates = true
     ignorecase = true
[remote "origin"]
     url = ../bareNetengPy.git/
     fetch = +refs/heads/*:refs/remotes/origin/*
$

    8c. Synchronize local with remote, note that nobody should do development in the remotes branch. It is serving as tracking point to track the commits made to the remote. The remote origin has no idea that somebody is pointing to it. 

$git branch -a
  dev
* master
$git remote update
Fetching origin
From ../bareNetengPy
 * [new branch]      dev        -> origin/dev
 * [new branch]      master     -> origin/master
$git branch -a
  dev
* master
  remotes/origin/dev
  remotes/origin/master
$

    8d. Do some local development work in dev, merge to master

$git checkout dev
Switched to branch 'dev'
$echo "This is a new file for sync." > syncFile.txt
$ls
foo          foo.py          hello.py     syncFile.txt
$git add syncFile.txt
$git commit -m "new commit in dev branch"
[dev 25413f6] new commit in dev branch
 Committer: Eric Chou <echou@pythonicneteng.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 syncFile.txt
$

$git show-branch -a
* [dev] new commit in dev branch
 ! [master] committed foo.py
  ! [origin/dev] commit foo.py to dev
   ! [origin/master] Added a comment
----
*    [dev] new commit in dev branch
 +   [master] committed foo.py
 + + [origin/master] Added a comment
 + + [origin/master^] Add first and second file
*+++ [origin/dev] commit foo.py to dev
$

$git checkout master
Switched to branch 'master'
$git merge dev
Merge made by recursive.
 syncFile.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 syncFile.txt
$

    8e. Push changes to origin

$git push origin master
Counting objects: 12, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 913 bytes, done.
Total 8 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
To ../bareNetengPy.git/
   7402862..4661300  master -> master
$

9. We hired a new engineer Bob and he is going to help with the projects: 

$# now pretend there is a new developer named Bob
$mkdir /tmp/bob
$cd /tmp/bob
$ls
$pwd
/tmp/bob
$git clone <path>/bareNetengPy.git/
Cloning into bareNetengPy...
done.
$

$ls
bareNetengPy
$cd bareNetengPy/
$ls
firstFile     foo.py          hello.py     secondFile     syncFile.txt
$git branch
* master
$git log -1
commit 46613006ded377a57d8d1c41ea9ed69a227ea6bc
Merge: 1abe355 25413f6
Author: Eric Chou <email>
Date:   Sun Oct 7 08:37:35 2012 -0700

    Merge branch 'dev'
$

    9a. Because Bob is cloned from origin, it automatically has the origin information:

$git remote show origin
* remote origin
  Fetch URL: <path>/bareNetengPy.git/
  Push  URL: <path>/bareNetengPy.git/
  HEAD branch: master
  Remote branches:
    dev    tracked
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)
$

$cat .git/config
[core]
     repositoryformatversion = 0
     filemode = true
     bare = false
     logallrefupdates = true
     ignorecase = true
[remote "origin"]
     fetch = +refs/heads/*:refs/remotes/origin/*
     url = <branch>/bareNetengPy.git/
[branch "master"]
     remote = origin
     merge = refs/heads/master
$

$git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
$

    9b. Make some changes and let Bob sync. 

$vi syncFile.txt
$git commit -m 'changes to syncFile.txt' -a
[master fdb64d2] changes to syncFile.txt
 Committer: Eric Chou <echou@pythonicneteng.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 files changed, 3 insertions(+), 0 deletions(-)
$git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 354 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To ../bareNetengPy.git/
   8bd4655..25413f6  dev -> dev
   4661300..fdb64d2  master -> master
$
$

$
$## Now Bob Returns and need to pull all the changes down
$
$cd /tmp/bob/
$ls
bareNetengPy
$cd bareNetengPy/
$ls
firstFile     foo.py          hello.py     secondFile     syncFile.txt
$cat syncFile.txt
This is a new file for sync.
$git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/echou/Desktop/Version_Control_with_Git/bareNetengPy
   8bd4655..25413f6  dev        -> origin/dev
   4661300..fdb64d2  master     -> origin/master
Updating 4661300..fdb64d2
Fast-forward
 syncFile.txt |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
$cat syncFile.txt
This is a new file for sync.

I am making some more changes and will allow other engineers sync

$

10. Here is a quick example of remote SSH:

AnotherComputer$cd /tmp
AnotherComputer$pwd
/tmp
AnotherComputer$
AnotherComputer$git clone ssh://<path>/bareNetengPy.git
Cloning into 'bareNetengPy'...
Password:
remote: Counting objects: 24, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 24 (delta 6), reused 0 (delta 0)
Receiving objects: 100% (24/24), done.
Resolving deltas: 100% (6/6), done.
AnotherComputer$ls
bareNetengPy               
AnotherComputer$pwd
/tmp
AnotherComputer$cd bareNetengPy/
AnotherComputer$ls -lia
total 40
26039637 drwxr-xr-x   8 echou  wheel  272 Oct  7 09:20 .
21154038 drwxrwxrwt  14 root   wheel  476 Oct  7 09:20 ..
26039638 drwxr-xr-x  13 echou  wheel  442 Oct  7 09:20 .git
26040114 -rw-r--r--   1 echou  wheel    4 Oct  7 09:20 firstFile
26040115 -rw-r--r--   1 echou  wheel   81 Oct  7 09:20 foo.py
26040116 -rw-r--r--   1 echou  wheel   22 Oct  7 09:20 hello.py
26040117 -rw-r--r--   1 echou  wheel    4 Oct  7 09:20 secondFile
26040118 -rw-r--r--   1 echou  wheel   97 Oct  7 09:20 syncFile.txt
AnotherComputer$cat syncFile.txt
This is a new file for sync.

I am making some more changes and will allow other engineers sync

AnotherComputer$

**********

Like I said, total overkill, but now I have a tool that is expandable for other projects as well! 

Leave me comments for any recommendations or questions. 






3 comments:

  1. Hey Eric, JJ here - may want to link to this as well: the entire "Pro Git" book by Apress is available here[1] for free. Was great for me to use as a resource when I was picking up this stuff.


    [1] http://git-scm.com/book

    ReplyDelete