Dan Hyun
Introduction
Git Now
Git Fundamentals
Git Commands
Everyday Git
Best Practices
Resources
Cross platform, distributed
source control management system.
Created in 2005 by Linus Torvalds
Used to maintain the Linux Kernel
Performance | fast, reliable file integrity |
Simplicity | no separate admin binaries |
Flexibility | supports multiple protocols, methods of contributions, etc. |
Create a new git repository
$ git init demo
Initialized empty Git repository in /home/vagrant/demo/.git/
$ echo 'public class Hello { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > Hello.java
$ javac Hello.java
$ java Hello
Hello, World!
$ git add Hello.java
$ git commit -m "Add important Hello.java file"
[master (root-commit) bf94b34] Add important Hello.java file
1 file changed, 1 insertion(+)
create mode 100644 Hello.java
Now you know git!
Objects
References
State
Distributed Nature
Every file is an object
Every commit is an object
These objects form a tree
HEAD
is a reference
Branches are references
Tags are references
Remotes are references
A given file can be in one of these four states:
Untracked
Tracked - not modified
Tracked - staged for commit
Committed
No central server or authority
Most actions performed locally
Eliminates issues (politics) around commit access
Attribute | Git | CVS/SVN |
---|---|---|
Tracking changes | Snapshot of all files | Per file |
History storage | Compressed binary objects with SHA1 checksum | Diff per file in .cvs/.svn directories |
Source of truth | Distributed | Centralized |
Used to set and get configuration properties
$ git config --list
user.name=Dan Hyun
user.email=dan@hyunlabs.com
Level | Config Location | Git flag |
---|---|---|
Project |
|
|
User |
|
|
System |
|
|
$ git config --global user.email "dan@hyunlabs.com"
$ git config --global user.name "Dan Hyun"
INFO: This information goes into your commits
Create a new Git repository
$ git init demo
Initialized empty Git repository in /home/vagrant/demo/.git/
init
.git
├── branches
├── config (1)
├── description
├── HEAD (2)
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── info
│ └── exclude
├── objects (3)
│ ├── info
│ └── pack
└── refs (4)
├── heads
└── tags
1 | Project level config file |
2 | Current branch reference |
3 | Blob storage |
4 | Reference locations |
Stages the given file(s) as is to the index
$ git add <file or path>
add
$ touch hello
$ git add hello
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello
$ find .git/objects/ -type f
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
Commit all staged objects to local repository
$ git commit [-m <message>]
commit
$ git commit -m "Initial commit"
[master (root-commit) d400d55] Initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 hello
$ find .git/objects -type f
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 (1)
.git/objects/f9/66952d7e0715683ee935d201cd4ab22736c831 (2)
.git/objects/d4/00d55d841364e0bdf479c5e172210954ae3d5c (3)
1 | Our hello file as a blob |
2 | Tree object containing fileset for commit |
3 | Commit object containing author and tree object |
git cat-file -p
allows us
to inspect git objects
$ git cat-file -p f966952d7e0715683ee935d201cd4ab22736c831
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 hello (1)
1 | File mode object type object hash |
Object types?
$ git cat-file -t e69de
blob
$ git cat-file -t f9669
tree
$ git cat-file -t d400d
commit
$ find .git/refs/ -type f
.git/refs/heads/master (1)
1 | New reference master added |
$ cat .git/refs/heads/master
d400d55d841364e0bdf479c5e172210954ae3d5c (1)
1 | The hash of the commit object |
git add everything
$ git add .
$ git commit -m "#yolo"
[master (root-commit) e96454d] #yolo
2 files changed, 1 insertion(+)
create mode 100644 Hello.class
create mode 100644 Hello.java
create mode 100644 Hello.class
$ git rm Hello.class
rm 'Hello.class'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: Hello.class
Don’t forget to commit
$ git commit -m "Remove generated files"
[master c36a69a] Remove generated files
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 Hello.class
.gitignore
lives at the root of the repository
# ignore generated files
*.class
# ignore maven output
target/
# ignore gradle output
build/
$ git branch neato-feature
$ git checkout neato-branch
Switched to branch 'neato-branch'
git branch
$ git branch -v
master c36a69a Remove generated files
* neato-branch c36a69a Remove generated files
$ echo "Hello is very important" > README
$ git add README
$ git commit -m README
[neato-branch 1f1f2ae] README
1 file changed, 1 insertion(+)
create mode 100644 README
$ git branch -v
master c36a69a Remove generated files
* neato-branch 1f1f2ae README
$ gitk
$ git checkout master
Switched to branch 'master'
$ git merge neato-branch
Updating c36a69a..1f1f2ae
Fast-forward
README | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README
$ git branch -v
* master 1f1f2ae README
neato-branch 1f1f2ae README
$ git remote add origin <URL> (1)
1 | Any valid URL |
$ git push origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (9/9), 1.09 KiB | 0 bytes/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To ../demo-remote
* [new branch] master -> master
$ git fetch
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 ../demo-remote
1f1f2ae..ecf757d master -> origin/master
$ git merge origin/master
Updating 1f1f2ae..ecf757d
Fast-forward
Hello.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git pull origin master
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 ../demo-remote
* branch master -> FETCH_HEAD
1f1f2ae..ecf757d master -> origin/master
Updating 1f1f2ae..ecf757d
Fast-forward
Hello.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
What happens when
code changes?
$ git push origin master
To ../demo-remote
! [rejected] master -> master (fetch first)
error: failed to push some refs to '../demo-remote'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
$ git pull origin master
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 ../demo-remote
* branch master -> FETCH_HEAD
ecf757d..fd10976 master -> origin/master
Auto-merging Hello.java
CONFLICT (content): Merge conflict in Hello.java
Automatic merge failed; fix conflicts and then commit the result.
$ cat Hello.java
<<<<<<< HEAD
public class Hello { public static void main(String[] args) { System.out.println("Hallo, Welt again!"); } }
=======
public class Hello { public static void main(String[] args) { System.out.println("Hello, World again!"); } }
>>>>>>> fd10976633568cd872f2d1aa64d97429957d73bb
$ git commit -am "resolve conflict"
[master b0ae7d5] resolve conflict
$ git push origin master
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 514 bytes | 0 bytes/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To ../demo-remote
fd10976..b0ae7d5 master -> master
Use commandline exclusively in the beginning
Adhere to your team’s work flow
Branch from your team’s canonical branch
Use consistent messaging
Use present tense and one line summary < 50 chars
Add paragraph with more details if needed
Reads like a log file:
Fixes duplicate entry issue
Update schema to use primary key
Update DAO to accept additional param
$ git clone https://chucknorris.com/roundhouse.git
Cloning into 'roundhouse'...
Password for 'https://chucknorris.com':
Generate an ssh key pair
Add public key to central server
Enjoy not typing passwords
$ ssh-keygen -t rsa -C "dan@hyunlabs.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/vagrant/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/vagrant/.ssh/id_rsa.
Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.
The key fingerprint is:
64:59:65:dc:ad:81:85:26:9e:ad:dd:d7:7a:21:75:e9 dan@hyunlabs.com
The key's randomart image is:
+--[ RSA 2048]----+
| .oo=.. |
| o..= o .|
| +. = o.|
| o o . .o.|
| S o .o o|
| . ...Eo|
| .o.|
| . .|
| . |
+-----------------+
Host *
PreferredAuthentications publickey,keyboard-interactive
ServerAliveInterval 120
ServerAliveCountMax 30
IdentityFile ~/.ssh/id_rsa
Host stash
User git
Hostname chucknorris.com
Port 7999
$ git clone stash:/roundhouse.git
Develop → Staging → Master
Commit to Master
Maintain two canonical branches (master, develop)
Master represents what is on production (always "deployable")
Develop is coordination branch
Branch from develop
Do some work
Merge from origin/develop if updated
Submit Pull Request*
Blog article by Scott Chacon about a workflow
Free ebook by Scott Chacon (Github) and Ben Straub
Series of labs to learn git fundamentals
Video - Linus talks about git
Interactive git command cheat sheet
A popular git branching model