Вы находитесь на странице: 1из 276

Introduction

to Git

$git me.name Ricardo Erikson


$git me.email ricardoerikson@gmail.com

If you are comfortable with version


control and its a version control that is
not git, you are going to hate git when
you start using it.
Scott Chacon (github co-founder)

git is an open source,


distributed version control
system designed for speed and
efficiency.

References
http://gitref.org
http://try.github.io
http://git-scm.com/doc
http://stackoverflow.com

distributed git

every developer is potentially both a


node or a hub

remote repository

remote repository

local repository

remote repository

git clone
git pull
git remote

local repository

remote repository

git clone
git pull
git remote

git push

local repository

you do a clone of the entire repository

which means
everything is fast
every clone is a backup
work offline

no network needed
performing a diff
viewing file history
committing changes

no network needed
merging branches
obtaining other revisions of a file
switching branches

subversion-style workflow
shared
repository

public

subversion-style workflow
shared
repository

developer

developer

private

public

developer

subversion-style workflow
shared
repository

developer

developer

private

public

developer

integration manager workflow

integration manager workflow

public
private

integration manager workflow

blessed
repository

public
private

integration manager workflow

blessed
repository

public
private

developer
public

developer
public

integration manager workflow

blessed
repository

public
private

integration
manager

developer
public

developer
public

integration manager workflow

blessed
repository

developer
public

developer
public

developer
private

developer
private

public
private

integration
manager

integration manager workflow


git push to publish the changes (commits)
to the remote repository
blessed
repository

developer
public

developer
public

developer
private

developer
private

public
private

integration
manager

integration manager workflow


merge request
blessed
repository

developer
public

developer
public

developer
private

developer
private

public
private

integration
manager

integration manager workflow


git push to publish the local changes
to the blessed repository
blessed
repository

developer
public

developer
public

developer
private

developer
private

public
private

integration
manager

integration manager workflow


git pull to update the local repository
blessed
repository

developer
public

developer
public

developer
private

developer
private

public
private

integration
manager

before starting

first-time git setup

first-time git setup


your identity
$ git config --global user.name Ricardo Erikson
$ git config --global user.email ricardoerikson@gmail.com

first-time git setup


your identity
$ git config --global user.name Ricardo Erikson
$ git config --global user.email ricardoerikson@gmail.com

colors in git
$ git config --global color.ui true

first-time git setup


your identity
$ git config --global user.name Ricardo Erikson
$ git config --global user.email ricardoerikson@gmail.com

colors in git
$ git config --global color.ui true

windows line-ending issues


$ git config --global core.autocrlf true

first-time git setup


your identity
$ git config --global user.name Ricardo Erikson
$ git config --global user.email ricardoerikson@gmail.com

colors in git
$ git config --global color.ui true

windows line-ending issues


$ git config --global core.autocrlf true

help
$ git help command

branching and merging


fundamentals

(git allows and encourages) multiple


local branches
fast creation, merging and deletion
branching is cheap

you can do things like

frictionless context switching


role-based codelines & feature based
workflow
disposable experimentation

frictionless context switching


master
develop

frictionless context switching


master
develop

topic branches

frictionless context switching


master
develop

topic branches

frictionless context switching


master
develop

topic branches

role-based codelines & feature


based workflow
master
develop

role-based codelines & feature


based workflow
master
develop

production
code

role-based codelines & feature


based workflow
master
develop

production
code
merge

role-based codelines & feature


based workflow
master
develop
feature/x
feature/y
bugfix/z

production
code
merge

disposable experimentation
master
develop

topic branches

disposable experimentation
master
develop

topic branches

disposable experimentation
master
develop

topic branches

disposable experimentation
master
develop

topic branches

getting and creating


projects

Initialize a new one


from an existing directory

Initialize a new one


from an existing directory

Clone one from a public


Git repository

git init

$ mkdir xpto-local

$ mkdir xpto-local
$ cd xpto-local

$ mkdir xpto-local
$ cd xpto-local
$ git init

$ mkdir xpto-local
$ cd xpto-local
$ git init
Initialized empty Git repository in /tmp/
mygitproject/.git/

$ mkdir xpto-local
$ cd xpto-local
$ git init
Initialized empty Git repository in /tmp/
mygitproject/.git/
$ ls -a

$ mkdir xpto-local
$ cd xpto-local
$ git init
Initialized empty Git repository in /tmp/
mygitproject/.git/
$ ls -a
. ..

.git

.
!"" .git
#"" HEAD
#"" config
#"" description
#"" hooks
$ #"" applypatch-msg.sample
$ #"" commit-msg.sample
$ #"" ...
$ #"" prepare-commit-msg.sample
$ !"" update.sample
#"" info
$ !"" exclude
#"" objects
$ #"" info
$ !"" pack
!"" refs
#"" heads
!"" tags
9 directories, 13 files

$ tree -a

.
!"" .git
#"" HEAD
#"" config
#"" description
#"" hooks
$ #"" applypatch-msg.sample
$ #"" commit-msg.sample
$ #"" ...
$ #"" prepare-commit-msg.sample
$ !"" update.sample
#"" info
$ !"" exclude
#"" objects
$ #"" info
$ !"" pack
!"" refs
#"" heads
!"" tags
9 directories, 13 files

$ tree -a
$ touch HelloWorld.java

.
!"" .git
#"" HEAD
#"" config
#"" description
#"" hooks
$ #"" applypatch-msg.sample
$ #"" commit-msg.sample
$ #"" ...
$ #"" prepare-commit-msg.sample
$ !"" update.sample
#"" info
$ !"" exclude
#"" objects
$ #"" info
$ !"" pack
!"" refs
#"" heads
!"" tags
9 directories, 13 files

$ tree -a
$ touch HelloWorld.java
$ git add .

.
!"" .git
#"" HEAD
#"" config
#"" description
#"" hooks
$ #"" applypatch-msg.sample
$ #"" commit-msg.sample
$ #"" ...
$ #"" prepare-commit-msg.sample
$ !"" update.sample
#"" info
$ !"" exclude
#"" objects
$ #"" info
$ !"" pack
!"" refs
#"" heads
!"" tags
9 directories, 13 files

$
$
$
$

tree -a
touch HelloWorld.java
git add .
git commit -m initial commit

.
#""
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
!""

$ tree -a

.git
$ touch HelloWorld.java
#"" ...
#"" config
$ git add .
#"" description
$ git commit -m initial
#"" hooks
$
#"" applypatch-msg.sample
$ tree -a
$
#"" commit-msg.sample
$
#"" ...
$
#"" pre-rebase.sample
$
#"" prepare-commit-msg.sample
$
!"" update.sample
#"" index
#"" info
$
!"" exclude
#"" logs
$
#"" HEAD
$
!"" refs
$
!"" heads
$
!"" master
#"" objects
$
#"" 66/4d5c28a7d49e6381d3e26d8b1e8d94576fd924
$
#"" 70/21125e13a868aadc609aad3ff2a7e325a2b986
$
#"" e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
$
#"" info
$
!"" pack
!"" refs
#"" heads
$
!"" master
!"" tags
HelloWorld.java

15 directories, 23 files

commit

$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = false

git clone

$ git clone git@10.224.200.6:projects/gitworkshop.git


Cloning into 'gitworkshop'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

$ git clone git@10.224.200.6:projects/gitworkshop.git


Cloning into 'gitworkshop'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
$ cd gitworkspace

$ git clone git@10.224.200.6:projects/gitworkshop.git


Cloning into 'gitworkshop'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
$ cd gitworkspace
$ ls -a
.

..

.git

HelloWorld.java

$ cat .git/config

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

staging area

staging area

Intermediate area where commits can be


formatted and reviewed before
completing the commit

working directory

staging area

repository

working directory
git add
staging area

repository

working directory
git add
staging area
git commit
repository

working directory

staging area

repository

git commit -a

working directory

staging area

repository

git commit -a

working directory

staging area

repository

git commit -a

working directory

Automatically stage files


that have been modified
and deleted

staging area

git commit -a

repository

working directory

Automatically stage files


that have been modified
and deleted

staging area

git commit -a
!

repository

New files are not


affected

basic snapshoting

git status
git diff
git add
git commit

git status shows the status of your file in the working


directory and stage area
git add adds file contents to the staging area

git status shows the status of your file in the working


directory and stage area
git add adds file contents to the staging area
$ git status -s
?? README
?? hello.rb

git status shows the status of your file in the working


directory and stage area
git add adds file contents to the staging area
$ git status -s
?? README
?? hello.rb
$ git add README hello.rb
A README
A hello.rb

git status shows the status of your file in the working


directory and stage area
git add adds file contents to the staging area
$ git status -s
?? README
?? hello.rb
$ git add README hello.rb
A README
A hello.rb
$ vim README
$ git status -s
AM README
A hello.rb

git diff shows diff of what is staged and what is


modified but unstaged

git diff shows diff of what is staged and what is


modified but unstaged
$ vim hello.rb

git diff shows diff of what is staged and what is


modified but unstaged
$ vim hello.rb
$ git status -s
M hello.rb

git diff shows diff of what is staged and what is


modified but unstaged
$ vim hello.rb
$ git status -s
M hello.rb
$ git diff

git diff shows diff of what is staged and what is


modified but unstaged
$ vim hello.rb
$ git status -s
M hello.rb
$ git diff
diff --git a/hello.rb b/hello.rb
index d62ac43..8d15d50 100644
--- a/hello.rb
+++ b/hello.rb
@@ -1,7 +1,7 @@
class HelloWorld

def self.hello
puts "hello world"
puts "hola mundo"
end
end

try other diff commands


git diff --cached shows diff of staged changes
git diff HEAD shows diff of all staged or
unstaged changes
git diff --stat shows summary of changes
instead of a full diff

try other diff commands


git diff --cached shows diff of staged changes
git diff HEAD shows diff of all staged or
unstaged changes
git diff --stat shows summary of changes
instead of a full diff

HEAD is like a pointer that


points to the current branch

git commit records a snapshot of the staging area

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
$ git add hello.rb

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
$ git add hello.rb
$ git status -s

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
$ git add hello.rb
$ git status -s
M hello.rb

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
$ git add hello.rb
$ git status -s
M hello.rb
$ git status

git commit records a snapshot of the staging area

$ git commit -m 'hola mundo changes'


[master 68aa034] hola mundo changes
1 files changed, 2 insertions(+), 1 deletions(-)
$ git add hello.rb
$ git status -s
M hello.rb
$ git status
# On branch master
nothing to commit (working directory clean)

basic git workflow


1

Edit files
Eclipse/Sublime/vim/emacs/etc

basic git workflow


1

Edit files
Eclipse/Sublime/vim/emacs/etc

Stage the changes


$git add (file)

basic git workflow


1

Edit files
Eclipse/Sublime/vim/emacs/etc

Stage the changes


$git add (file)

Review the changes


$git diff / $git status

basic git workflow


1

Edit files
Eclipse/Sublime/vim/emacs/etc

Stage the changes


$git add (file)

Review the changes


$git diff / $git status

Commit the changes


$git commit

or
1

Edit files
Eclipse/Sublime/vim/emacs/etc

or
1

Edit files
Eclipse/Sublime/vim/emacs/etc

Stage and commit


$git commit -a

or
1

Edit files
Eclipse/Sublime/vim/emacs/etc

Stage and commit


$git commit -a

Use git commit --amend to edit an


incorrect commit message (last commit)

git reset

git reset undoes changes and commits

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb
$ git add .

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb
$ git add .
$ git status -s
M README
M hello.rb

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb
$ git add .
$ git status -s
M README
M hello.rb
$ git reset HEAD -- hello.rb
Unstaged changes after reset:
M hello.rb

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb
$ git add .
$ git status -s
M README
M hello.rb
$ git reset HEAD -- hello.rb
Unstaged changes after reset:
M hello.rb
$ git status -s
M README
M hello.rb

git reset undoes changes and commits


git reset HEAD unstages files from index
and reset pointer from index
$ git status -s
M README
M hello.rb
$ git add .
$ git status -s
M README
M hello.rb
$ git reset HEAD -- hello.rb
Unstaged changes after reset:
M hello.rb
$ git status -s
M README
M hello.rb

Be careful

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)
$ git status
# On branch master
nothing to commit (working directory clean)

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)
$ git status
# On branch master
nothing to commit (working directory clean)
$ git reset --soft HEAD~

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)
$ git status
# On branch master
nothing to commit (working directory clean)
$ git reset --soft HEAD~
$ git status -s
M hello.rb

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)
$ git status
# On branch master
nothing to commit (working directory clean)
$ git reset --soft HEAD~
$ git status -s
M hello.rb

the last commit will be undone and


the files touched will be back on
the stage again

git reset --soft moves HEAD to the specified commit reference,


index and staging are untouched
$ git status -s
M hello.rb
$ git commit -am 'hello with a flower'
[master 5857ac1] hello with a flower
1 files changed, 3 insertions(+), 1 deletions(-)
$ git status
# On branch master
nothing to commit (working directory clean)
$ git reset --soft HEAD~
$ git status -s
M hello.rb

the last commit will be undone and


the files touched will be back on
the stage again

use it to undo local commits

git reset --hard unstages files AND undoes any changes in the
working directory since last commit

$
#
#
#
#
#
#

git reset --hard unstages files AND undoes any changes in the
working directory since last commit

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

README

git reset --hard unstages files AND undoes any changes in the
working directory since last commit

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

git reset --hard unstages files AND undoes any changes in the
working directory since last commit

$ git status
# On branch master
# Changes to be committed:
#
(use "git reset HEAD <file>..." to unstage)
#
# modified:
README
#
# Changes not staged for commit:
#
(use "git add <file>..." to update what will be committed)
#
(use "git checkout -- <file>..." to discard changes in working
directory)
#
# modified:
README
#
$ git reset --hard HEAD
HEAD is now at 5857ac1 hello with a flower

git reset --hard unstages files AND undoes any changes in the
working directory since last commit

$ git status
# On branch master
# Changes to be committed:
#
(use "git reset HEAD <file>..." to unstage)
#
# modified:
README
#
# Changes not staged for commit:
#
(use "git add <file>..." to update what will be committed)
#
(use "git checkout -- <file>..." to discard changes in working
directory)
#
# modified:
README
#
$ git reset --hard HEAD
HEAD is now at 5857ac1 hello with a flower
$ git status
# On branch master
nothing to commit (working directory clean)

git rm

git rm removes files from the staging area

To leave the file in the working directory,


you can use git rm --cached

git mv
git rm --cached orig
mv orig new
git add new

git rm removes files from the staging area


kicks the file off the stage entirely,
so that it's not included in the next
commit snapshot, thereby effectively deleting it

To leave the file in the working directory,


you can use git rm --cached

git mv
git rm --cached orig
mv orig new
git add new

git stash

git stash saves changes made in the current


index and working directory for later

git stash saves changes made in the current


index and working directory for later

$ git status -s
M hello.rb

git stash saves changes made in the current


index and working directory for later

$ git status -s
M hello.rb
$ git stash
Saved working directory and index state WIP on master: 5857ac1
hello with a flower
HEAD is now at 5857ac1 hello with a flower

git stash saves changes made in the current


index and working directory for later

$ git status -s
M hello.rb
$ git stash
Saved working directory and index state WIP on master: 5857ac1
hello with a flower
HEAD is now at 5857ac1 hello with a flower
$ git status
# On branch master
nothing to commit (working directory clean)

git stash saves changes made in the current


index and working directory for later

$ git status -s
M hello.rb
$ git stash
Saved working directory and index state WIP on master: 5857ac1
hello with a flower
HEAD is now at 5857ac1 hello with a flower
$ git status
# On branch master
nothing to commit (working directory clean)

use git stash -u to also stash unversioned files

git stash saves changes made in the current


index and working directory for later
you're in the middle of some changes but
something comes up that you need to
jump over to
$ git status -s
M hello.rb
$ git stash
Saved working directory and index state WIP on master: 5857ac1
hello with a flower
HEAD is now at 5857ac1 hello with a flower
$ git status
# On branch master
nothing to commit (working directory clean)

use git stash -u to also stash unversioned files

git stash adds current changes to the stack

git stash adds current changes to the stack


git stash list view stashes currently on the stack

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower
$ vim hello.rb

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower
$ vim hello.rb
$ git commit -am 'it stops raining'
[master ee2d2c6] it stops raining
1 files changed, 1 insertions(+), 1 deletions(-)

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower
$ vim hello.rb
$ git commit -am 'it stops raining'
[master ee2d2c6] it stops raining
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim hello.rb

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower
$ vim hello.rb
$ git commit -am 'it stops raining'
[master ee2d2c6] it stops raining
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim hello.rb
$ git stash
Saved working directory and index state WIP on master:
ee2d2c6 it stops raining
HEAD is now at ee2d2c6 it stops raining

git stash adds current changes to the stack


git stash list view stashes currently on the stack
$ git stash list
stash@{0}: WIP on master: 5857ac1 hello with a flower
$ vim hello.rb
$ git commit -am 'it stops raining'
[master ee2d2c6] it stops raining
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim hello.rb
$ git stash
Saved working directory and index state WIP on master:
ee2d2c6 it stops raining
HEAD is now at ee2d2c6 it stops raining
$ git stash list
stash@{0}: WIP on master: ee2d2c6 it stops raining
stash@{1}: WIP on master: 5857ac1 hello with a flower

git stash apply grabs the item from the stash list
and apply to current working directory

git stash apply grabs the item from the stash list
and apply to current working directory
$ git stash apply

git stash apply grabs the item from the stash list
and apply to current working directory
$ git stash apply
# On branch master
# Changes not staged for commit:
#
(use "git add <file>..." to update what will be committed)
#
(use "git checkout -- <file>..." to discard changes in working
directory)
#
# modified:
hello.rb
#
no changes added to commit (use "git add" and/or "git commit -a")

by default it will reapply the last added


stash item to the working directory.

by default it will reapply the last added


stash item to the working directory.

the last added stash item is referenced by stash@{0}

by default it will reapply the last added


stash item to the working directory.

the last added stash item is referenced by stash@{0}

you can grab another stash item instead if you


reference it in the argument list

by default it will reapply the last added


stash item to the working directory.

the last added stash item is referenced by stash@{0}

you can grab another stash item instead if you


reference it in the argument list

$ git stash apply stash@{1}

git tag

git tag tags a point in history as important

$ git tag -a v1.0 tag the current commit as v1.0

git tag tags a point in history as important

$ git tag -a v1.0 tag the current commit as v1.0

say we had released commit 558151a (several commits


back) but forgot to tag it at the time

git tag tags a point in history as important

$ git tag -a v1.0 tag the current commit as v1.0

say we had released commit 558151a (several commits


back) but forgot to tag it at the time
$ git tag -a v1.0 558151a

git tag tags a point in history as important

$ git tag -a v1.0 tag the current commit as v1.0

say we had released commit 558151a (several commits


back) but forgot to tag it at the time
$ git tag -a v1.0 558151a
you can:
$ git checkout -b new_branch v1.0

git log

git log shows commit history of a branch


$ git log
$ git log --oneline
$ git log --oneline --graph
$ git log --oneline --graph --decorate
$ git log --oneline develop
$ git log --author='Ricardo Erikson
$ git log --oneline --before={3.weeks.ago} -after={2010-04-18} no-merges
$ git log --graph --pretty=format:'%Cred%h%Creset %C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>
%Creset' abbrev-commit
$ git config alias.lol "log --color --graph -pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s
%Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

branching and merging

git branch
git checkout

git branch lists, creates and manages working contexts


git checkout switches to a new branch context

git branch lists, creates and manages working contexts


git checkout switches to a new branch context

$ git branch
* master

git branch lists, creates and manages working contexts


git checkout switches to a new branch context

$ git branch
* master

there is a master branch and


we are currently on it

git branch lists, creates and manages working contexts


git checkout switches to a new branch context

$ git branch
* master

there is a master branch and


we are currently on it

git init will automatically create a master


branch for you by default

$ echo C0 >> arq.txt && git commit -a

$ echo C0 >> arq.txt && git commit -a

C0
master

$ echo C0 >> arq.txt && git commit -a


$ echo C1 >> arq.txt && git commit -a

C0

C1
master

$ echo C0 >> arq.txt && git commit -a


$ echo C1 >> arq.txt && git commit -a
$ git checkout -b develop

develop
C0

C1
master

$
$
$
$

echo C0 >>
echo C1 >>
git checkout
echo C2 >>

develop
C0

C1
master

C2

arq.txt && git commit -a


arq.txt && git commit -a
-b develop
arq.txt && git commit -a

$
$
$
$
$

echo C0 >>
echo C1 >>
git checkout
echo C2 >>
echo C3 >>

arq.txt &&
arq.txt &&
-b develop
arq.txt &&
arq.txt &&

develop
C0

C1
master

C2

C3

git commit -a
git commit -a
git commit -a
git commit -a

$
$
$
$
$
$

echo C0 >>
echo C1 >>
git checkout
echo C2 >>
echo C3 >>
git checkout

arq.txt && git


arq.txt && git
-b develop
arq.txt && git
arq.txt && git
-b feature/f1

feature/f1
develop
C0

C1
master

C2

C3

commit -a
commit -a
commit -a
commit -a

git branch (branchname) creates a new branch

git branch (branchname) creates a new branch


$ git branch
* master

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README

hello.rb

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt
$ git add *.txt

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt
$ git add *.txt
$ git commit -m 'added two files'
[master 8bd6d8b] added two files
2 files changed, 2 insertions(+),
0 deletions(-)
create mode 100644 more.txt
create mode 100644 test.txt

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt
$ git add *.txt
$ git commit -m 'added two files'
[master 8bd6d8b] added two files
2 files changed, 2 insertions(+),
0 deletions(-)
create mode 100644 more.txt
create mode 100644 test.txt
$ ls
README
hello.rb more.txt test.txt

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt
$ git add *.txt
$ git commit -m 'added two files'
[master 8bd6d8b] added two files
2 files changed, 2 insertions(+),
0 deletions(-)
create mode 100644 more.txt
create mode 100644 test.txt
$ ls
README
hello.rb more.txt test.txt
$ git checkout testing
Switched to branch 'testing'

git branch (branchname) creates a new branch


$ git branch
* master
$ git branch testing
$ git branch
* master
testing

$ ls
README
hello.rb
$ echo 'test content' > test.txt
$ echo 'more content' > more.txt
$ git add *.txt
$ git commit -m 'added two files'
[master 8bd6d8b] added two files
2 files changed, 2 insertions(+),
0 deletions(-)
create mode 100644 more.txt
create mode 100644 test.txt
$ ls
README
hello.rb more.txt test.txt
$ git checkout testing
Switched to branch 'testing'
$ ls
README
hello.rb

try other branch commands

try other branch commands


git checkout -b (branchname) creates and
immediately switch to a branch

try other branch commands


git checkout -b (branchname) creates and
immediately switch to a branch

try other branch commands


git checkout -b (branchname) creates and
immediately switch to a branch
$ git branch branchname
$ git checkout branchname

try other branch commands


git checkout -b (branchname) creates and
immediately switch to a branch
$ git branch branchname
$ git checkout branchname
git branch -v see the last commit on each branch

try other branch commands


git checkout -b (branchname) creates and
immediately switch to a branch
$ git branch branchname
$ git checkout branchname
git branch -v see the last commit on each branch
git branch -d delete a branch

git merge

git merge merges a branch context into your current one


git merge fixes merges branch fixes on top of
the current branch
git merge --no-ff fixes creates a merge commit
even when the merge resolves as a fast-forward
git merge --abort aborts the current conflict
resolution process

feature/f1
C0

C1
master

C2

C3
develop

$ echo C4 >> arq.txt && git commit -a

feature/f1
C0

C1
master

C2

C3
develop

C4

$ echo C4 >> arq.txt && git commit -a


$ echo C5 >> arq.txt && git commit -a

feature/f1
C0

C1
master

C2

C3
develop

C4

C5

$ echo C4 >> arq.txt && git commit -a


$ echo C5 >> arq.txt && git commit -a
$ echo C6 >> arq.txt && git commit -a

feature/f1
C0

C1
master

C2

C3
develop

C4

C5

C6

$
$
$
$

echo C4 >>
echo C5 >>
echo C6 >>
git checkout

arq.txt && git commit -a


arq.txt && git commit -a
arq.txt && git commit -a
develop

feature/f1
C0

C1
master

C2

C3
develop

C4

C5

C6

$
$
$
$
$

echo C4 >> arq.txt && git commit -a


echo C5 >> arq.txt && git commit -a
echo C6 >> arq.txt && git commit -a
git checkout develop
git merge feature/f1

feature/f1
C0

C1
master

C2

C3

C4

C5

C6
develop

feature/f1
C4

C0

C1
master

C2

C3
develop

C5

C6

$ echo C4 >> arq.txt && git commit -a

feature/f1
C4

C0

C1
master

C2

C3

C4
develop

C5

C6

$ echo C4 >> arq.txt && git commit -a


$ git merge feature/f1

feature/f1
C4

C0

C1
master

C2

C3

C4

C5

C6

C7
develop

git clone git@10.224.200.6:projects/merge.git

git clone git@10.224.200.6:projects/merge.git

$
$
$
$
$

git
git
git
vim
git

checkout -b change_class
mv HelloWorld.java HiWorld.java
status
HelloWorld.java (Change the class name to HiWorld)
commit -am Changed class name

git clone git@10.224.200.6:projects/merge.git

$
$
$
$
$

git
git
git
vim
git

checkout -b change_class
mv HelloWorld.java HiWorld.java
status
HelloWorld.java (Change the class name to HiWorld)
commit -am Changed class name

$ git checkout master


$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi World message

git clone git@10.224.200.6:projects/merge.git

$
$
$
$
$

git
git
git
vim
git

checkout -b change_class
mv HelloWorld.java HiWorld.java
status
HelloWorld.java (Change the class name to HiWorld)
commit -am Changed class name

$ git checkout master


$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi World message

$ git merge [--no-ff] change_class

resolving conflicts
Conflicts mean parallel evolutions of the same content

common
ancestor

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message
$ git checkout master
$ vim HelloWorld.java (Write Ola mundo message)
$ git commit -am Ola mundo message

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message
$ git checkout master
$ vim HelloWorld.java (Write Ola mundo message)
$ git commit -am Ola mundo message
$ git merge change_class

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message
$ git checkout master
$ vim HelloWorld.java (Write Ola mundo message)
$ git commit -am Ola mundo message
$ git merge change_class

Conflicts!

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message
$ git checkout master
$ vim HelloWorld.java (Write Ola mundo message)
$ git commit -am Ola mundo message
$ git merge change_class

Conflicts!

$ git merge -s [ours|theirs] change_class


$ git checkout --[ours|theirs] file

for each file

git clone git@10.224.200.6:projects/merge.git


$ git reset hard origin/master
$ git checkout -b change_message
$ vim HelloWorld.java (Write Hi World message)
$ git commit -am Hi world message
$ git checkout master
$ vim HelloWorld.java (Write Ola mundo message)
$ git commit -am Ola mundo message
$ git merge change_class

Conflicts!

$ git merge -s [ours|theirs] change_class


$ git checkout --[ours|theirs] file

After resolving merge conflicts!


$ git commit -a

for each file

git rebase

git rebase is a different way to integrate changes


of one branch into another

you can take all the changes that were committed


on one branch and replay them on another one

git rebase is a different way to integrate changes


of one branch into another

you can take all the changes that were committed


on one branch and replay them on another one

rebase with develop at least once a day

feature/f1
C5

C0

C1
master

C2

C3

C4
develop

$ git checkout feature/f1

feature/f1
C5

C0

C1
master

C2

C3

C4
develop

$ git checkout feature/f1


$ git rebase develop

feature/f1
C0

C1
master

C2

C3

C4
develop

C5

$ git checkout feature/f1


$ git rebase develop
$ git checkout develop

feature/f1
C0

C1
master

C2

C3

C4
develop

C5

$
$
$
$

git
git
git
git

checkout feature/f1
rebase develop
checkout develop
merge feature/f1

feature/f1
C0

C1
master

C2

C3

C4

C5
develop

rebase vs. merge (short version)

merge takes all the changes in one branch and merge


them into another branch in one commit
rebase says I want the point which I branched to move
to a new starting point

rebase vs. merge (long version)


merge
Let's say you have created a branch for the purpose of
developing a single feature. When you want to bring those
changes back to master, you probably want merge
rebase
A second scenario would be if you started doing some
development and then another developer made an
unrelated change. You probably want to pull and then
rebase to base your changes from the current version from
the repo.

sharing and updating


projects

git remote

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote
$ git remote add github git@github.com:schacon/hw.git

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote
$ git remote add github git@github.com:schacon/hw.git
$ git remote -v
githubgit@github.com:schacon/hw.git (fetch)
githubgit@github.com:schacon/hw.git (push)

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote
$ git remote add github git@github.com:schacon/hw.git
$ git remote -v
githubgit@github.com:schacon/hw.git (fetch)
githubgit@github.com:schacon/hw.git (push)

git remote rm removes an existing remote alias

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote
$ git remote add github git@github.com:schacon/hw.git
$ git remote -v
githubgit@github.com:schacon/hw.git (fetch)
githubgit@github.com:schacon/hw.git (push)

git remote rm removes an existing remote alias


$ git remote rm github

git remote lists, adds and deletes remote repository


aliases
git remote add adds a new remote repository to your
project
$ git remote
$ git remote add github git@github.com:schacon/hw.git
$ git remote -v
githubgit@github.com:schacon/hw.git (fetch)
githubgit@github.com:schacon/hw.git (push)

git remote rm removes an existing remote alias


$ git remote rm github
$ git remote -v

git fetch
git pull

git fetch downloads new branches and data from


a remote repository (like git remote update)
git pull fetches from a remote repo and try to merge
into the current branch

git fetch downloads new branches and data from


a remote repository (like git remote update)
git pull fetches from a remote repo and try to merge
into the current branch
$ git fetch github
remote: Counting objects: 4006, done.
remote: Compressing objects: 100% (1322/1322), done.
remote: Total 2783 (delta 1526), reused 2587 (delta 1387)
Receiving objects: 100% (2783/2783), 1.23 MiB | 10 KiB/s, done.
Resolving deltas: 100% (1526/1526), completed with 387 local
objects.
From github.com:schacon/hw
8e29b09..c7c5a10 master
-> github/master
0709fdc..d4ccf73 c-langs
-> github/c-langs
6684f82..ae06d2b java
-> github/java
* [new branch]
ada
-> github/ada
* [new branch]
lisp
-> github/lisp

git push

git push pushes your new branches and data to


a remote repository

$ git push origin develop

git push pushes your new branches and data to


a remote repository

remote alias
$ git push origin develop

git push pushes your new branches and data to


a remote repository

remote alias
$ git push origin develop
branch

$ git push github master


Counting objects: 25, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (25/25), done.
Writing objects: 100% (25/25), 2.43 KiB, done.
Total 25 (delta 4), reused 0 (delta 0)
To git@github.com:schacon/hw.git
* [new branch]
master -> master

$ git push github master


Counting objects: 25, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (25/25), done.
Writing objects: 100% (25/25), 2.43 KiB, done.
Total 25 (delta 4), reused 0 (delta 0)
To git@github.com:schacon/hw.git
* [new branch]
master -> master

$ git push github master


To git@github.com:schacon/hw.git
! [rejected]
master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:schacon/hw.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.

developer 1 (local)

shared repository

developer 2 (local)

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

developer 1 (local)

clone (state1)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

state1

commit

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

commit

state2

commit

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

commit

state2

commit

commit

state2

commit

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

commit

state2

commit

commit

state2

commit

commit

state3

push (state3)

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

commit

state2

commit

commit

state2

commit

commit

state3

push (state3)

push

state3

developer 1 (local)

shared repository

developer 2 (local)

state0

clone (state0)

state0

commit

state0

commit

state1

push (state1)

clone (state1)

state1

commit

commit

state1

commit

commit

state2

push (state2)

commit

state2

commit

commit

state2

commit

commit

state3

push (state3)

push

state3

rejected!

$ git push github master


To git@github.com:schacon/hw.git
! [rejected]
master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:schacon/hw.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.

you could force with $ git push github master --force

$ git push github master


To git@github.com:schacon/hw.git
! [rejected]
master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:schacon/hw.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.

you could force with $ git push github master --force

be careful!

$ git push github master


To git@github.com:schacon/hw.git
! [rejected]
master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:schacon/hw.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast-forwards' section of 'git push --help' for details.

you could force with $ git push github master --force

be careful!

correct procedure should be:


$ git fetch github
$ git merge github/master
$ git push github master

useful things

aliases
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.lol log --oneline --graph --decorate

undo conflict resolution


$ git checkout -m file

git blame
git bisect
git revert

git show
git diff
git request-pull

you are encouraged to combine commands


collaborate with other developers on:
github.com (Build software better, together)
gitorious.org

Вам также может понравиться