You are on page 1of 37

GIT/GERRIT TRAINING

GIT/Gerrit know-how
GIT training agenda

 Introduction
 Setup & First commit
 Three states & Basic workflow
 History and old revisions
 Fix mistakes
 Undoing local changes
 Undoing staged changes
 Undoing committed changes
 Amending changes
 Git internals
 Branching
 Resolving conflicts
 Merge
 Rebase
 Cherry-pick
 Rewriting history
 Multiple repositories
 Tips & tricks

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 2


GIT training – Branching

 Branching
 Creating branch (local)
 Navigating branches
 Merging vs Rebasing
 Resolving conflicts

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 3


GIT training – Creating a branch (local)

 It‟s time to do a major rewrite of the hello world functionality. Since this
might take awhile, you‟ll want to put these changes into a separate branch
to isolate them from changes in master.
lukic@gtv02-lin-$ git checkout -b dev-lukic
Switched to a new branch 'dev-lukic‘
lukic@gtv02-lin-$ git branch
* dev-lukic
master
lukic@gtv02-lin-$ git status
# On branch dev-lukic
nothing to commit, working directory clean
lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git commit -m "First commit on dev-lukic branch"
[dev-lukic 4b3b71a] First commit on dev-lukic branch
1 file changed, 1 insertion(+)

 NOTE: git checkout -b <branchname> is a shortcut for git


branch <branchname> followed by a git checkout <branchname>.
 Notice that the git status command reports that you are on the „dev-
lukic‟ branch.
 git branch command can be used to print all present branches (current
branch is selected with * prefix and with green color)
CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 4
GIT training – Navigating branches

 First check the status:


lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short --all
* 4b3b71a 2014-05-24 | First commit on dev-lukic branch (HEAD, dev-lukic) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory (master) [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 Just use the git checkout command to switch between branches.


lukic@gtv02-lin-$ git checkout master
Switched to branch 'master'
lukic@gtv02-lin-$ cat src/main.c
First change!
Second change!
Third change!
lukic@gtv02-lin-$ git checkout dev-lukic
Switched to branch 'dev-lukic'
lukic@gtv02-lin-$ cat src/main.c
First change!
Second change!
Third change!
Change on new branch!

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 5


GIT training – Changes in master (1/5)

 Now, our small project have two branches (master and dev-lukic),
where dev-lukic is “ahead” of master by one commit. Lets use git
log command to examine status on both branches:
 master branch
lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short master
* 756aa57 2014-05-24 | Moved main.c to src directory (master) [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 dev-lukic

lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short dev-lukic
* 4b3b71a 2014-05-24 | First commit on dev-lukic branch (HEAD, dev-lukic) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory (master) [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 6


GIT training – Changes in master (2/5)

 It is normal that master branch continue to evolve, in parallel with dev-


lukic branch. Lets add one more commit on master branch:
lukic@gtv02-lin-$ git checkout master
Switched to branch 'master'
lukic@gtv02-lin-$ touch Readme.txt
lukic@gtv02-lin-$ vi Readme.txt
lukic@gtv02-lin-$ git add Readme.txt
lukic@gtv02-lin-$ git commit -m "Adding Readme file"
[master fe6efcc] Adding Readme file
1 file changed, 1 insertion(+)
create mode 100644 Readme.txt

 Current graph of these two branches look like this:

CL1 CL2 CL3 CL4 CL5 CL7 master

CL6 dev-lukic

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 7


GIT training – Changes in master (3/5)

 Lets use git log command to examine status on both branches:


 master branch (Readme file commit is added)
lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short master
* fe6efcc 2014-05-24 | Adding Readme file (master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 dev-lukic (didn‟t change)


lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short dev-lukic
* 4b3b71a 2014-05-24 | First commit on dev-lukic branch (HEAD, dev-lukic) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory (master) [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 These two branches diverge from 756aa57 commit

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 8


GIT training – Changes in master (4/5)

 How to resolve this?


 How to reintegrate CL7 in dev-lukic (usually it is good practice, before
committing back CL6 from dev-lukic to master, to put it “on-top” of
master branch, which may change from the point of “branching-off”)

 So, what we want is:

CL1 CL2 CL3 CL4 CL5 CL7 master

CL7 CL6 dev-lukic

 How to do it?

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 9


GIT training – Changes in master (5/5)

 Using git rebase command, you can put all work from dev-lukic “on-
top” of current state of master branch:
lukic@gtv02-lin-$ git checkout dev-lukic
Switched to branch 'dev-lukic'
lukic@gtv02-lin-$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: First commit on dev-lukic branch
lukic@gtv02-lin-$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short --all
* 22de96b 2014-05-24 | First commit on dev-lukic branch (HEAD, dev-lukic) [Nemanja Lukic]
* fe6efcc 2014-05-24 | Adding Readme file (master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

CL1 CL2 CL3 CL4 CL5 CL7 master

X CL6' dev-lukic

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 10


GIT training – Viewing diverging branches
(1/4)

 First, lets add one more commit on dev-lukic branch:


lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git commit -m "Second commit on dev-lukic branch"
[dev-lukic a0ec4c3] Second commit on dev-lukic branch
1 file changed, 1 insertion(+)
lukic@gtv02-lin-$ cat src/main.c
First change!
Second change!
Third change!
Change on new branch!
Second change on new branch!
lukic@gtv02-lin-$ git hist --all
* a0ec4c3 2014-05-25 | Second commit on dev-lukic branch (HEAD, dev-lukic) [Nemanja Lukic]
* 22de96b 2014-05-24 | First commit on dev-lukic branch [Nemanja Lukic]
* fe6efcc 2014-05-24 | Adding Readme file (master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 11


GIT training – Viewing diverging branches
(2/4)

 Second, lets add one more branch (dev-lukic2), witch starts from
master, with one commit:
lukic@gtv02-lin-$ git checkout master
Switched to branch 'master'
lukic@gtv02-lin-$ git checkout -b dev-lukic2
Switched to a new branch 'dev-lukic2'
lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git commit -m "First commit on dev-lukic2 branch"
[dev-lukic2 e300f98] First commit on dev-lukic2 branch
1 file changed, 1 insertion(+)
lukic@gtv02-lin-$ git hist --all
* e300f98 2014-05-25 | First commit on dev-lukic2 branch (HEAD, dev-lukic2) [Nemanja Lukic]
| * a0ec4c3 2014-05-25 | Second commit on dev-lukic branch (dev-lukic) [Nemanja Lukic]
| * 22de96b 2014-05-24 | First commit on dev-lukic branch [Nemanja Lukic]
|/
* fe6efcc 2014-05-24 | Adding Readme file (master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 12


GIT training – Viewing diverging branches
(3/4)

 Graph of the project, now looks like this:


CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9

lukic@gtv02-lin-$ git tree


* e300f98 - (2 minutes ago) First commit on dev-lukic2 branch - Nemanja Lukic (HEAD, dev-lukic2)
| * a0ec4c3 - (10 minutes ago) Second commit on dev-lukic branch - Nemanja Lukic (dev-lukic)
| * 22de96b - (2 hours ago) First commit on dev-lukic branch - Nemanja Lukic
|/
* fe6efcc - (2 hours ago) Adding Readme file - Nemanja Lukic (master)
* 756aa57 - (3 hours ago) Moved main.c to src directory - Nemanja Lukic
* 459273f - (3 hours ago) My fourth commit - Nemanja Lukic
* 9492649 - (6 hours ago) My third commit - Nemanja Lukic (tag: v1)
* 6cfaf1c - (14 hours ago) My second commit - Nemanja Lukic (tag: v1-beta)
* 4ae7eb5 - (15 hours ago) My first commit - Nemanja Lukic

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 13


GIT training – Viewing diverging branches
(4/4)

 Other GUI based graph tools for git:


 apt-get install gitk giggle

gitk giggle

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 14


GIT training – Viewing changes

 To look specific commit use git show <SHA1> command. If used


without parameter, it will show last commit on top of the current branch.
lukic@gtv02-lin-$ git checkout dev-lukic lukic@gtv02-lin-$ git checkout dev-lukic2
Switched to branch 'dev-lukic' Switched to branch 'dev-lukic2'
lukic@gtv02-lin-$ git show lukic@gtv02-lin-$ git show
commit a0ec4c3ec22c60daa7bf5eaed9c58f52951ea8f4 commit e300f98a138fd8a941b8dfe5422ff7cd9f681e4d
Author: Nemanja Lukic <nemanja.lukic@rt-rk.com> Author: Nemanja Lukic <nemanja.lukic@rt-rk.com>
Date: Sun May 25 01:52:24 2014 +0200 Date: Sun May 25 02:00:13 2014 +0200

Second commit on dev-lukic branch First commit on dev-lukic2 branch

diff --git a/src/main.c b/src/main.c diff --git a/src/main.c b/src/main.c


index d72075e..f8e51d3 100644 index 6dfe881..b0f48d4 100644
--- a/src/main.c --- a/src/main.c
+++ b/src/main.c +++ b/src/main.c
@@ -2,3 +2,4 @@ First change! @@ -1,3 +1,4 @@
Second change! First change!
Third change! Second change!
Change on new branch! Third change!
+Second change on new branch! +First commit on dev-lukic2 branch!

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 15


GIT training agenda

 Introduction
 Setup & First commit
 Three states & Basic workflow
 History and old revisions
 Fix mistakes
 Undoing local changes
 Undoing staged changes
 Undoing committed changes
 Amending changes
 Git internals
 Branching
 Resolving conflicts
 Merge
 Rebase
 Cherry-pick
 Rewriting history
 Multiple repositories
 Tips & tricks

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 16


GIT training – Resolving conflicts (1/6)

 Until this point, there was no conflict situations.


 When rebasing dev-lukic on top of master, rebased commit didn‟t address files
changed on master branch in the mean time (Readme.txt)
 What if we want to “rebase” dev-lukic2 branch on top of dev-lukic
branch. On both branches same file is changed (main.c). This may cause
conflict which needs to be resolved.
 git rebase command usually can resolve “simple” conflict situations,
but most of the time, manual merge is needed.

 What we want to achieve is this:


CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 17


GIT training – Resolving conflicts (2/6)

 Rebase command outputs following:


lukic@gtv02-lin-$ git rebase dev-lukic
First, rewinding head to replay your work on top of it...
Applying: First commit on dev-lukic2 branch
Using index info to reconstruct a base tree...
M src/main.c
Falling back to patching base and 3-way merge...
Auto-merging src/main.c
CONFLICT (content): Merge conflict in src/main.c
Failed to merge in the changes.
Patch failed at 0001 First commit on dev-lukic2 branch
The copy of the patch that failed is found in:
/home/lukic/git/project/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

 As expected, when trying to apply commit from dev-lukic2 branch on top


of dev-lukic branch, conflict occurred (they both change close range of
lines in main.c)

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 18


GIT training – Resolving conflicts (3/6)

 Using git diff command we can see what is actually being staged after
git rebase (actual conflict situation):
lukic@gtv02-lin-$ git diff
diff --cc src/main.c
index f8e51d3,b0f48d4..0000000
--- a/src/main.c
+++ b/src/main.c
@@@ -1,5 -1,4 +1,9 @@@
First change!
Second change!
Third change!
++<<<<<<< HEAD
+Change on new branch!
+Second change on new branch!
++=======
+ First commit on dev-lukic2 branch!
++>>>>>>> First commit on dev-lukic2 branch

 The first section (<<<<<<< HEAD) is the version of the code on the head of
the dev-lukic branch (on which we are rebasing). The second section
(starting with =======) is the version on the dev-lukic2 branch (from
commit we are rebasing).

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 19


GIT training – Resolving conflicts (4/6)

 Conflict resolution is always manual. You have to decide how to merge file
changes (take from the HEAD, or from local branch, both, or something in
between)
lukic@gtv02-lin-$ git diff lukic@gtv02-lin-$ vi src/main.c
diff --cc src/main.c lukic@gtv02-lin-$ cat src/main.c
index f8e51d3,b0f48d4..0000000 First change!
--- a/src/main.c Second change!
+++ b/src/main.c Third change!
@@@ -1,5 -1,4 +1,9 @@@
First change! => Change on new branch!
Second change on new branch!
First commit on dev-lukic2 branch!
Second change!
Third change!
++<<<<<<< HEAD
+Change on new branch!
+Second change on new branch!
++=======
+ First commit on dev-lukic2 branch!
++>>>>>>> First commit on dev-lukic2 branch

 After resolving conflict (in this case, combine changes from the HEAD and
from local change), stage the change, and continue with rebasing process.
 Since this new change is “altered” original change, usually it is marked
(with apostrophe) to emphasize this fact.

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 20


GIT training – Resolving conflicts (5/6)

lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git rebase --continue
Applying: First commit on dev-lukic2 branch

 This process is repeated for every conflict


 git rebase --abort and git rebase --skip can be used at any
stage of rebase process, to abort rebasing, or skip current conflicting patch
lukic@gtv02-lin-$ git tree
* eacf4f7 - (46 minutes ago) First commit on dev-lukic2 branch - Nemanja Lukic (HEAD, dev-lukic2)
* a0ec4c3 - (54 minutes ago) Second commit on dev-lukic branch - Nemanja Lukic (dev-lukic)
* 22de96b - (3 hours ago) First commit on dev-lukic branch - Nemanja Lukic
* fe6efcc - (3 hours ago) Adding Readme file - Nemanja Lukic (master)
* 756aa57 - (4 hours ago) Moved main.c to src directory - Nemanja Lukic
* 459273f - (4 hours ago) My fourth commit - Nemanja Lukic
* 9492649 - (6 hours ago) My third commit - Nemanja Lukic (tag: v1)
* 6cfaf1c - (15 hours ago) My second commit - Nemanja Lukic (tag: v1-beta)
* 4ae7eb5 - (15 hours ago) My first commit - Nemanja Lukic

CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9'

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 21


GIT training – Resolving conflicts (6/6)

 git checkout --ours src/main.c


 git checkout --theirs src/main.c

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 22


GIT training – Rebase vs Merge (1/5)

 Merge process

=>

 Because the commit on the branch you‟re on (experiment) isn‟t a direct ancestor of the
branch you‟re merging in (master), Git has to do some work.
 In this case, Git does a simple three-way merge, using the two snapshots pointed to by the
branch tips and the common ancestor of the two.
 This results in a NEW commit, that bridges differences in experiment and master branch

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 23


GIT training – Rebase vs Merge (2/5)

 Merge process example:


lukic@gtv02-lin-$ git checkout master
Switched to branch 'master'
lukic@gtv02-lin-$ git checkout -b dev-lukic3
Switched to a new branch 'dev-lukic3'
lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git commit -m "First commit on dev-lukic3 branch"
[dev-lukic3 7dceaa4] First commit on dev-lukic3 branch
1 file changed, 1 insertion(+)
lukic@gtv02-lin-$ cat src/main.c
First change!
Second change!
Third change!
First change on dev-lukic3 branch!

 Current project status is:


CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9'

CL10
CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 24
GIT training – Rebase vs Merge (3/5)

 Lets try merge dev-lukic3 in dev-lukic branch:


lukic@gtv02-lin-$ git checkout dev-lukic
Switched to branch 'dev-lukic'
lukic@gtv02-lin-$ git merge dev-lukic3
Auto-merging src/main.c
CONFLICT (content): Merge conflict in src/main.c
Automatic merge failed; fix conflicts and then commit the result.
lukic@gtv02-lin-$ vi src/main.c
lukic@gtv02-lin-$ git add src/main.c
lukic@gtv02-lin-$ git commit
[dev-lukic d62ec86] Merge branch 'dev-lukic3' into dev-lukic
lukic@gtv02-lin-$ git hist
* d62ec86 2014-05-25 | Merge branch 'dev-lukic3' into dev-lukic (HEAD, dev-lukic) [Nemanja Lukic]
|\
| * 7dceaa4 2014-05-25 | First commit on dev-lukic3 branch (dev-lukic3) [Nemanja Lukic]
* | a0ec4c3 2014-05-25 | Second commit on dev-lukic branch [Nemanja Lukic]
* | 22de96b 2014-05-24 | First commit on dev-lukic branch [Nemanja Lukic]
|/
* fe6efcc 2014-05-24 | Adding Readme file (master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 As expected, there was conflict!


 Merge process resulted in new commit, which is on top of the branched
where merge was performed
CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 25
GIT training – Rebase vs Merge (4/5)

 Rebase process (already showed):

 Conflict resolution is done on experiment branch


 No extra commits on master branch

 After rebase, rebased commit can be integrated back into master using merge (but now
fast-forward), or using cherry-pick command:

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 26


GIT training – Rebase vs Merge (5/5)

 The final result of the rebase is very similar to the merge. However, the
commit tree is quite different. Rebase command leaves the chain of
commits linear and much easier to read.

 Always use rebase!


 When rebase is not recommended:
 Do not rebase commits that you have pushed to a public repository
 Rewriting publicly shared branches will tend to screw up other members of the team
 When the exact history of the commit branch is important (since rebase rewrites the commit
history)
 Or in other words, in VERY rare occasions

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 27


GIT training – His Royal Highness
Cherry-pick (1/3)

 When merging two branches, instead of using git merge (with resolving
conflicts, which adds new unnecessary commits), ALWAYS use git
rebase, together with git cherry-pick command.

 First, using rebase, put commit on development branch in line with top of
the branch, where you want to merge it. Transform this:

CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9'

CL10

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 28


GIT training – His Royal Highness
Cherry-pick (2/3)

 Into this:
CL1 CL5 CL7 master

CL6 CL8 dev-lukic

CL9'

CL10'

 After that, you only need to checkout dev-lukic branch, and cherry-
pick CL10‟:
lukic@gtv02-lin-$ git checkout dev-lukic
Switched to branch 'dev-lukic‘
lukic@gtv02-lin-$ git cherry-pick 74c17af
[dev-lukic bf689d7] First commit on dev-lukic3 branch
1 file changed, 1 insertion(+)

 Since all conflicts are resolved on dev-lukic3, while rebasing, cherry-


pick command is clean, and keeps history well formatted
CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 29
GIT training – His Royal Highness
Cherry-pick (3/3)

 Why rebase (on local branch) + cherry-pick (on


integration branch), over merge?
 Keeps history clean (no “merge” commits)
 Who does the conflict resolution? -> Developer on development
branch
 Who doesn‟t do conflict resolution? -> Integrator
 The one who develops the change is responsible for keeping it
up-to-date (testing on top of integration branch)

 This principle is core of Gerrit review process …

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 30


GIT training agenda

 Introduction
 Setup & First commit
 Three states & Basic workflow
 History and old revisions
 Fix mistakes
 Undoing local changes
 Undoing staged changes
 Undoing committed changes
 Amending changes
 Git internals
 Branching
 Resolving conflicts
 Merge
 Rebase
 Cherry-pick
 Rewriting history
 Multiple repositories
 Tips & tricks

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 31


GIT training – Playing god

 What if you suddenly realize that some very old commit needs to be
changed. And, you don‟t want to put commit that will fix it. You want clean
history, so basically you want to change already merged commit.
 This is not possible, right? -> NO, it is possible.
 You can do this!

 Lets see how to update second commit - 6cfaf1c (both change and commit
message):
lukic@gtv02-lin-$ git hist local_dev-lukic3
* 16da2cd 2014-05-25 | Remote branch dev-lukic3 updated (HEAD, local_dev-lukic3) [Nemanja Lukic]
* f1fe903 2014-05-25 | First commit on local branch (origin/dev-lukic3) [Nemanja Lukic]
* 74c17af 2014-05-25 | First commit on dev-lukic3 branch [Nemanja Lukic]
* a0ec4c3 2014-05-25 | Second commit on dev-lukic branch [Nemanja Lukic]
* 22de96b 2014-05-24 | First commit on dev-lukic branch [Nemanja Lukic]
* fe6efcc 2014-05-24 | Adding Readme file (origin/master) [Nemanja Lukic]
* 756aa57 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 459273f 2014-05-24 | My fourth commit [Nemanja Lukic]
* 9492649 2014-05-24 | My third commit (tag: v1) [Nemanja Lukic]
* 6cfaf1c 2014-05-24 | My second commit (tag: v1-beta) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 32


GIT training – Interactive rebase (1/4)

 Run rebase with -i parameter, which is SHA1 of the last “good” commit:
lukic@gtv02-lin-$ git rebase -i 4ae7eb5

 This opens interactive window, where you can see all commit from last
“good” commit to the top of the current branch, listed chronologically:
pick 6cfaf1c My second commit
pick 9492649 My third commit
pick 459273f My fourth commit
pick 756aa57 Moved main.c to src directory
pick fe6efcc Adding Readme file
pick 22de96b First commit on dev-lukic branch
pick a0ec4c3 Second commit on dev-lukic branch
pick 74c17af First commit on dev-lukic3 branch
pick f1fe903 First commit on local branch
pick 16da2cd Remote branch dev-lukic3 updated

# Rebase 4ae7eb5..16da2cd onto 4ae7eb5


#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 33


GIT training – Interactive rebase (2/4)

 Mark commit you want to change with edit (6cfaf1c), and change the rest
with the reword:
edit 6cfaf1c My second commit
reword 9492649 My third commit
reword 459273f My fourth commit
reword 756aa57 Moved main.c to src directory
reword fe6efcc Adding Readme file
reword 22de96b First commit on dev-lukic branch
reword a0ec4c3 Second commit on dev-lukic branch
reword 74c17af First commit on dev-lukic3 branch
reword f1fe903 First commit on local branch
reword 16da2cd Remote branch dev-lukic3 updated

 When you leave editor, you will be in the rebase mode, and pointing to the
commit you marked for editing:
lukic@gtv02-lin-$ git rebase -i 4ae7eb5
Stopped at 6cfaf1c... My second commit
You can amend the commit now, with

git commit --amend

Once you are satisfied with your changes, run

git rebase --continue

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 34


GIT training – Interactive rebase (3/4)

 Change the commit, and amend the log. Than continue with rebasing:
lukic@gtv02-lin-$ vi main.c
lukic@gtv02-lin-$ git status
# HEAD detached from 4ae7eb5
# You are currently editing a commit while rebasing branch 'local_dev-lukic3' on '4ae7eb5'.
# (use "git commit --amend" to amend the current commit)
# (use "git rebase --continue" once you are satisfied with your changes)
#
# 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: main.c
#
no changes added to commit (use "git add" and/or "git commit -a")
lukic@gtv02-lin-$ git add main.c
lukic@gtv02-lin-$ git commit --amend
[detached HEAD 4bad84f] My second commit (after interactive rebase)
1 file changed, 1 insertion(+)
lukic@gtv02-lin-$ git rebase --continue

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 35


GIT training – Interactive rebase (4/4)

 Lets examine history now:


lukic@gtv02-lin-$ git hist
* 9bcad2f 2014-05-25 | First commit on local branch (HEAD, local_dev-lukic3) [Nemanja Lukic]
* 8df2c00 2014-05-25 | First commit on dev-lukic3 branch [Nemanja Lukic]
* 109a0e3 2014-05-25 | Second commit on dev-lukic branch [Nemanja Lukic]
* 427bf42 2014-05-24 | First commit on dev-lukic branch [Nemanja Lukic]
* d4cb2c5 2014-05-24 | Adding Readme file [Nemanja Lukic]
* 8c128ed 2014-05-24 | Moved main.c to src directory [Nemanja Lukic]
* 738ba00 2014-05-24 | My fourth commit [Nemanja Lukic]
* 2bb03de 2014-05-24 | My third commit [Nemanja Lukic]
* 1079cc9 2014-05-24 | My second commit (after interactive rebase) [Nemanja Lukic]
* 4ae7eb5 2014-05-24 | My first commit [Nemanja Lukic]

 Note the different SHA1 for every commit after 4ae7eb5

CONFIDENTIAL – Reproduction prohibited without the prior permission of RT-RK 36


Contact us

RT-RK Institute for Computer Based Systems


Narodnog fronta 23a
21000 Novi Sad
Serbia

www.rt-rk.com
info@rt-rk.com

You might also like