Here we are covering subjects related to branches.
git checkout <sha1>
\ git checkout <tag_name>
git checkout master
git branch
can tell you to which branch HEAD is pointing to.
git branch -v
gives you more information about branches and commit points and messages (-v is verbose)If you give git checkout –b feature
Now we are ready to merge feature with master.
You can also create a new branch like below, it creates a new feature12-test branch based on master branch.
1git checkout -b feature12-test master
Two steps of merging
Make a note of the strategy in the above diagram recursive
This is a fast-forward merge
Going back to the Recursive Strategy (or) 3-way merge
“the commit on the branch you’re on isn’t a direct ancestor of the branch you’re merging in, 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.”
Git uses 3 commits to generate a merge commit
Once the branches are merged they can be deleted
Git branch --merged
git branch –d feature
NOTE:- Git will not allow a branch to be deleted if its not merged. Use the below command to forcibly delete the branch.
git branch –D feature
Create a new tracking branch based on a remote branch
1git branch --track <new-branch> <remote-branch>
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test4 (master)2$ git branch3* master4
5Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test4 (master)6$ git checkout -b name17Switched to a new branch 'name1'8
9Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test4 (name1)10$ git branch11 master12* name113
14Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test4 (name1)15$ git branch -m name216
17Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test4 (name2)18$ git branch19 master20* name2
If you have made some unstaged changes in the working directory and try to checkout to new branch. You will not be able to do it. During then use,
git stash
Switching branches
1git checkout master2git checkout dev3
4# here - means master5git checkout -6
7# here - means dev8git checkout -
Reflog is short for reference log, is a mechanism to record when the tip of branches are updated. Git tries really hard not to lose your data, so if for some reason you think it has, chances are you can dig it out using git reflog.
The most common usecase, you made some changes and committed those and did a git reset --hard
to “undo” those changes, and then later realized, you want those changes back. Usecase for this would be any scenario where you move your HEAD. With reflog you can recover almost anything you’ve committed
Git refs are updated when below commands are executed
git reflog
is similar to git log
but shows list of times when HEAD is changed.
Things to remember
git checkout -- <filename>
, HEAD does not change, so reflog cannot recover those. git reflog
does not last forever as git periodically cleans up objects which are unreachable. Its a global setting, by default it keeps for 90 days. Common reflog commands are
git reflog
/ git reflog show HEAD
git reflog show <<branch>>
git reflog stash
Scenario above
Rebasing is changing the base of your branch from one commit to another making it appear as if you’d created your branch from a different commit. Internally, Git accomplishes this by creating new commits and applying them to the specified base. It’s very important to understand that even though the branch looks the same, it’s composed of entirely new commits.
get merge
. Before rebase
1A---B---C feature(head)2 /3 D---E---F---G master
Assuming here you are currently on your feature branch(git checkout feature
) and when you enter (git rebase master
) following happens,
git reset --hard <master>
During rebase (step 3)
1feature(head)2 /3 D---E---F---G master
After rebase command completion(A', B' and C' will have new SHA1-hashes)
1A'--B'--C' feature(head)2 /3 D---E---F---G master
Command git rebase master feature
combines above two command into a single command, what it does is,
At this point, you can go back to the master branch and do a fast-forward merge as well.
1git checkout master2git merge feature3
4# Visual Output 5 feature6 |7 D---E---F---G---A'---B'---C' master(head)
You can remove the feature branche because all the work is integrated into master you don’t need it anymore.
1git branch -d feature
git checkout
to feature1git checkout master2git merge feature
Note : Its not recommended to rebase master onto a feature branch as it would create confusing history when working with multiple people in a team. Dont do something like the following,
1git checkout master2git rebase feature
Other options
git rebase --abort
Plan is to squash last two commits(260b361, 25bde47) into one
Latest 10 commits
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)2$ git lol -n103* 260b361 - (HEAD -> master) Deleting a c d e text files (1 year, 10 months ago) <Sushanth Bobby Lloyds>4* 25bde47 - (tag: V4, stash/start) Updated readme.txt & adding back c d e (1 year, 10 months ago) <Sushanth Bobby Lloyds>5* d4bff73 - (tag: V3) Merge reset/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>6|\7| * 1ab856b - (reset/finished) Adding a.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>8|/9* b77ca73 - (reset/start) Updated readme.txt for RESET (1 year, 10 months ago) <Sushanth Bobby Lloyds>10* 85e7f70 - (tag: V2) Merge undo/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>11|\12| * db8427c - (undo/finished) Revert "Updated OneTwoThreeFour.txt line 2 from Two to number 2" (1 year, 10 months ago) <Sushanth Bobby Lloyds>13| * 178a3ca - Updated OneTwoThreeFour.txt line 4 from Four to number 4 (1 year, 10 months ago) <Sushanth Bobby Lloyds>14| * 6405ecb - Updated OneTwoThreeFour.txt line 2 from Two to number 2 (1 year, 10 months ago) <Sushanth Bobby Lloyds>15| * 3ebe1db - Adding OneTwoThreeFour.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>
Squashing latest two commits git rebase -i HEAD~2
. As soon as i entered the command, vim editor window poped up and listed the two commits in chronological order with command pick
and manually changed second commit command to squash
.
1pick 25bde47 Updated readme.txt & adding back c d e2squash 260b361 Deleting a c d e text files3
4# Rebase d4bff73..260b361 onto d4bff73 (2 commands)5#6# Commands:7# p, pick = use commit8# r, reword = use commit, but edit the commit message9# e, edit = use commit, but stop for amending10# s, squash = use commit, but meld into previous commit11# f, fixup = like "squash", but discard this commit's log message12# x, exec = run command (the rest of the line) using shell13# d, drop = remove commit14#15# These lines can be re-ordered; they are executed from top to bottom.16#17# If you remove a line here THAT COMMIT WILL BE LOST.18#19# However, if you remove everything, the rebase will be aborted.20#21# Note that empty commits are commented out
After Esc -> :wq
(save & exit), another editor pops up like below, this is for rewriting the comment message.
1# This is a combination of 2 commits.2# This is the 1st commit message:3
4Updated readme.txt & adding back c d e5
6# This is the commit message #2:7
8Deleting a c d e text files9
10# Please enter the commit message for your changes. Lines starting11# with '#' will be ignored, and an empty message aborts the commit.12#13# Date: Mon Dec 10 19:48:44 2018 +053014#15# interactive rebase in progress; onto d4bff7316# Last commands done (2 commands done):17# pick 25bde47 Updated readme.txt & adding back c d e18# squash 260b361 Deleting a c d e text files19# No commands remaining.20# You are currently rebasing branch 'master' on 'd4bff73'.21#22# Changes to be committed:23# deleted: a.txt24# modified: readme.txt25#26# Untracked files:27# Branching.txt28#
Commented existing comments by insert # symbol and added inserted message squashing two commits (Updated readme.txt & adding back c d e, Deleting a c d e text files)
then save & exit.
This is the final output
1$ git rebase -i HEAD~22[detached HEAD 745f48c] squashing two commits (Updated readme.txt & adding back c d e, Deleting a c d e text files)3 Date: Mon Dec 10 19:48:44 2018 +05304 2 files changed, 64 insertions(+), 1 deletion(-)5 delete mode 100644 a.txt6Successfully rebased and updated refs/heads/master.7
8Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)9$ git lol -n 510* 745f48c - (HEAD -> master) squashing two commits (Updated readme.txt & adding back c d e, Deleting a c d e text files) (6 minutes ago) <Sushanth Bobby Lloyds>11* d4bff73 - (tag: V3) Merge reset/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>12|\13| * 1ab856b - (reset/finished) Adding a.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>14|/15* b77ca73 - (reset/start) Updated readme.txt for RESET (1 year, 10 months ago) <Sushanth Bobby Lloyds>16* 85e7f70 - (tag: V2) Merge undo/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>17|\
If this is what you had expected, then this is fine otherwise you can undo the above action by doing.
1$ git reflog -n 102745f48c (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to refs/heads/master3745f48c (HEAD -> master) HEAD@{1}: rebase -i (squash): squashing two commits (Updated readme.txt & adding back c d e, Deleting a c d e text files)425bde47 (tag: V4, stash/start) HEAD@{2}: rebase -i (start): checkout HEAD~25260b361 HEAD@{3}: rebase -i (abort): updating HEAD6260b361 HEAD@{4}: rebase: aborting7d4bff73 (tag: V3) HEAD@{5}: rebase -i (start): checkout HEAD~28260b361 HEAD@{6}: reset: moving to ORIG_HEAD9be43d59 HEAD@{7}: rebase -i (finish): returning to refs/heads/master10be43d59 HEAD@{8}: rebase -i (squash): Updated readme.txt & adding back c d e117ac6472 HEAD@{9}: rebase -i (reword): Updated readme.txt & adding back c d e12
13Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)14$ git reset --hard "HEAD@{3}"15HEAD is now at 260b361 Deleting a c d e text files16
17Sushanth@Sushanth-VAIO MINGW64 /d/GITs/git (master)18$ git lol -n 1019* 260b361 - (HEAD -> master) Deleting a c d e text files (1 year, 10 months ago) <Sushanth Bobby Lloyds>20* 25bde47 - (tag: V4, stash/start) Updated readme.txt & adding back c d e (1 year, 10 months ago) <Sushanth Bobby Lloyds>21* d4bff73 - (tag: V3) Merge reset/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>22|\23| * 1ab856b - (reset/finished) Adding a.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>24|/25* b77ca73 - (reset/start) Updated readme.txt for RESET (1 year, 10 months ago) <Sushanth Bobby Lloyds>26* 85e7f70 - (tag: V2) Merge undo/finished into master (1 year, 10 months ago) <Sushanth Bobby Lloyds>27|\28| * db8427c - (undo/finished) Revert "Updated OneTwoThreeFour.txt line 2 from Two to number 2" (1 year, 10 months ago) <Sushanth Bobby Lloyds>29| * 178a3ca - Updated OneTwoThreeFour.txt line 4 from Four to number 4 (1 year, 10 months ago) <Sushanth Bobby Lloyds>30| * 6405ecb - Updated OneTwoThreeFour.txt line 2 from Two to number 2 (1 year, 10 months ago) <Sushanth Bobby Lloyds>31| * 3ebe1db - Adding OneTwoThreeFour.txt (1 year, 10 months ago) <Sushanth Bobby Lloyds>
Instead of git reflog
, git reset --hard "HEAD@{n}"
and all the detective stuff above, you can just enter this command as well git reset --hard ORIG_HEAD
.
Any other issues with rebase, you can do
git add
then 'git rebase --continue`git rebase --abort
git reset --hard
This is a big topic has its own pro and con and decision needs to be based on collaborators and team,
git merge
is run, an extra merge commit is created, so there might be too many merge commits. git rebase
is risky insense, it rewrites historygit rebase
can be used to squash commits locallyConflicts occur when there are changes to the same position/line of the file at different commits or branches Usually conflicts occur during
Test Setup
1rm -rf .git *.*2git init3
4echo "Big bang" > universe.txt5git add .6git commit -m "Initial Commit"7echo "Sun" >> universe.txt && git commit -am "Added Sun"8echo "Mercury" >> universe.txt && git commit -am "Added mercury"9echo "Venus" >> universe.txt && git commit -am "Added venus"10echo "Earth" >> universe.txt && git commit -am "Added earth"11echo "Mars" >> universe.txt && git commit -am "Added mars"12echo "Jupiter" >> universe.txt && git commit -am "Added jupiter"13echo "Saturn" >> universe.txt && git commit -am "Added saturn"14echo "Uranus" >> universe.txt && git commit -am "Added uranus"15echo "Neptune" >> universe.txt && git commit -am "Added neptune"
Content of file and commits
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)2$ cat universe.txt3Big bang4Sun5Mercury6Venus7Earth8Mars9Jupiter10Saturn11Uranus12Neptune13
14Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)15$ git lol16* bc3b214 - (HEAD -> master) Added neptune (9 seconds ago) <Sushanth Bobby Lloyds>17* 1bc7ec8 - Added uranus (11 seconds ago) <Sushanth Bobby Lloyds>18* 1cb6a2c - Added saturn (11 seconds ago) <Sushanth Bobby Lloyds>19* 479fc63 - Added jupiter (11 seconds ago) <Sushanth Bobby Lloyds>20* 762ee6e - Added mars (11 seconds ago) <Sushanth Bobby Lloyds>21* ff9623a - Added earth (12 seconds ago) <Sushanth Bobby Lloyds>22* 8dd1b51 - Added venus (12 seconds ago) <Sushanth Bobby Lloyds>23* 4790be6 - Added mercury (3 minutes ago) <Sushanth Bobby Lloyds>24* 56f3e34 - Added Sun (3 minutes ago) <Sushanth Bobby Lloyds>25* e1d1d72 - Initial Commit (4 minutes ago) <Sushanth Bobby Lloyds>
As part of test, i am going to remove commit related to Earth
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)2$ git revert ff9623a3error: could not revert ff9623a... Added earth4hint: after resolving the conflicts, mark the corrected paths5hint: with 'git add <paths>' or 'git rm <paths>'6hint: and commit the result with 'git commit'7
8Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)9$ cat universe.txt10Big bang11Sun12Mercury13Venus14 <<<<<<< HEAD15Earth16Mars17Jupiter18Saturn19Uranus20Neptune21=======22 >>>>>>> parent of ff9623a... Added earth
Git adds below markers(seven <,> & = symbols) when a conflict is found and its the developers responsibility to remove the markers after manually reviewing the program
<<<<<<< HEAD
=======
>>>>>>> parent of ff9623a... Added earth
Manually markers and Earth needs to be removed.
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)2$ git status3On branch master4You are currently reverting commit ff9623a.5 (fix conflicts and run "git revert --continue")6 (use "git revert --abort" to cancel the revert operation)7
8Unmerged paths:9 (use "git reset HEAD <file>..." to unstage)10 (use "git add <file>..." to mark resolution)11
12 both modified: universe.txt13
14no changes added to commit (use "git add" and/or "git commit -a")15
16Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)17$ cat universe.txt18Big bang19Sun20Mercury21Venus22Mars23Jupiter24Saturn25Uranus26Neptune27
28Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)29$ git add .30
31Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)32$ git status33On branch master34You are currently reverting commit ff9623a.35 (all conflicts fixed: run "git revert --continue")36 (use "git revert --abort" to cancel the revert operation)37
38Changes to be committed:39 (use "git reset HEAD <file>..." to unstage)40
41 modified: universe.txt42
43Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|REVERTING)44$ git revert --continue45[master 6e6cfa5] Revert "Added earth"46 1 file changed, 1 deletion(-)47
48Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)49$ git lol50* 6e6cfa5 - (HEAD -> master) Revert "Added earth" (13 seconds ago) <Sushanth Bobby Lloyds>51* bc3b214 - Added neptune (42 minutes ago) <Sushanth Bobby Lloyds>52* 1bc7ec8 - Added uranus (42 minutes ago) <Sushanth Bobby Lloyds>53* 1cb6a2c - Added saturn (42 minutes ago) <Sushanth Bobby Lloyds>54* 479fc63 - Added jupiter (42 minutes ago) <Sushanth Bobby Lloyds>55* 762ee6e - Added mars (42 minutes ago) <Sushanth Bobby Lloyds>56* ff9623a - Added earth (42 minutes ago) <Sushanth Bobby Lloyds>57* 8dd1b51 - Added venus (42 minutes ago) <Sushanth Bobby Lloyds>58* 4790be6 - Added mercury (44 minutes ago) <Sushanth Bobby Lloyds>59* 56f3e34 - Added Sun (44 minutes ago) <Sushanth Bobby Lloyds>60* e1d1d72 - Initial Commit (45 minutes ago) <Sushanth Bobby Lloyds>
As soon as you hit git revert --continue
, vim editor pops up for comment message which is auto-filled, you can go with it. Save, Exit and you have completed the reverting process.
Note : Read git status
messages, they will give you options and commands on how to proceed. Above, it gave two options
(all conflicts fixed: run "git revert --continue")
(use "git revert --abort" to cancel the revert operation)
Conflicts during merging branches
Scenario : Developer wants to write a calculator program in rexx and basically wants two features add() and sub() initially and quickly writes the below main logic and each feature is added in separate branch.
1# calc.txt contains below code2/*** rexx ***/3a = 104b = 55c = add(a, b)6d = sub(a, b)7say 'Addition : 'c8say 'Subractiion : 'd9exit
Creating branches
1git init2git add .3git commit -m 'Initial commit'4git checkout -b add5# Add add()6git add . && git commit -m "Added add feature"7
8git checkout master9git checkout -b sub10# Add sub()11git add . && git commit -m "Added sub feature"
Add feature
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)2$ git checkout add3Switched to branch 'add'4
5Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (add)6$ cat calc.txt7/*** rexx ***/8a = 109b = 510c = add(a, b)11d = sub(a, b)12say 'Addition : 'c13say 'Subractiion : 'd14exit15
16add:procedure17get argument a18get argument b19say 'Adding a + b'20return 0
Sub feature
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (add)2$ git checkout sub3Switched to branch 'sub'4
5Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (sub)6$ cat calc.txt7/*** rexx ***/8a = 109b = 510c = add(a, b)11d = sub(a, b)12say 'Addition : 'c13say 'Subractiion : 'd14exit15
16sub:procedure17get argument a18get argument b19say ‘Subracting a - b'20return 0
Merging add and sub features
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (sub)2$ git checkout master3Switched to branch 'master'4
5Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)6$ git merge add sub7Fast-forwarding to: add8Trying simple merge with sub9Simple merge did not work, trying automatic merge.10Auto-merging calc.txt11ERROR: content conflict in calc.txt12fatal: merge program failed13Automatic merge failed; fix conflicts and then commit the result.14
15$ cat calc.txt16/*** rexx ***/17a = 1018b = 519c = add(a, b)20d = sub(a, b)21say 'Addition : 'c22say 'Subractiion : 'd23exit24
25<<<<<<< .merge_file_a1413626add:procedure27get argument a28get argument b29say 'Adding a + b'30=======31sub:procedure32get argument a33get argument b34say ‘Subracting a - b'35>>>>>>> .merge_file_a1340036return 0
Removed the markers and proceeded to stage and commit
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|MERGING)2$ git status3On branch master4You have unmerged paths.5 (fix conflicts and run "git commit")6 (use "git merge --abort" to abort the merge)7
8Unmerged paths:9 (use "git add <file>..." to mark resolution)10
11 both modified: calc.txt12
13no changes added to commit (use "git add" and/or "git commit -a")14
15Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|MERGING)16$ git add .17warning: LF will be replaced by CRLF in calc.txt.18The file will have its original line endings in your working directory.19
20Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master|MERGING)21$ git commit -m 'Added both add and sub'22[master c35ab3e] Added both add and sub23
24Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)25$26
27Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)28$ git lol29* c35ab3e - (HEAD -> master) Added both add and sub (32 seconds ago) <Sushanth Bobby Lloyds>30|\31| * 447bd6a - (sub) Added sub feature (9 minutes ago) <Sushanth Bobby Lloyds>32* | 8671031 - (add) Added add feature (11 minutes ago) <Sushanth Bobby Lloyds>33|/34* 216acda - Initial commit (13 minutes ago) <Sushanth Bobby Lloyds>35
36# Deleted the branches as they are no longer required. 37git branch -D add38git branch -D sub
More changes & conflicts
Adding proper code to add function
1git checkout -b add2
3# add function in the current code is replaced with below4add:procedure5a = arg(1)6b = arg(2)7say 'Adding a + b'8return a + b9
10git add .11git commit -m 'Updated add()'12
13git checkout master
Adding proper code to add function
1git checkout -b sub2
3# sub function in the current code is replaced with below4sub:procedure5a = arg(1)6b = arg(2)7say 'Subracting a - b'8return a - b9
10git add .11git commit -m 'Updated add()'12
13git checkout master
Merging calc.txt with master
1Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)2$ git merge add sub3Fast-forwarding to: add4Trying simple merge with sub5Simple merge did not work, trying automatic merge.6Auto-merging calc.txt7warning: LF will be replaced by CRLF in calc.txt.8The file will have its original line endings in your working directory.9Merge made by the 'octopus' strategy.10 calc.txt | 14 +++++++-------11 1 file changed, 7 insertions(+), 7 deletions(-)12
13Sushanth@Sushanth-VAIO MINGW64 /d/GITs/test3 (master)14$ git status15On branch master16nothing to commit, working tree clean
No conflicts this time as each of the developers updated different part of the code, different lines. Additionally if you notice here we have been merging two branches to master in a single command and strategy we are using in ‘octopus’
“This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branch. “
This is experimental, its sort of similar to git checkout <branch-name>
as it does switch to a specified branch. The working tree and the index are updated to match the branch. All new commits will be added to the tip of this branch.
Most common operations are
git switch feature-v1
: Switching to feature-v1 branch git switch -c feature-v1
: (caps-off)Creating a new branch git switch -C feature-v1
: (caps-on)If a branch already exists, it will reset the start point. git switch -
: Switches to last branch git switch -m feature-v1
: Does a 3-way mergeCreating a branch from old commit
There are multiple ways to do like
Using checkout : git checkout -b feature-pre-v1 a9c146a09505837ec03b
Using branch but without checking out git branch feature-pre-v1 a9c146a09505837ec03b
Via detached HEAD
1git checkout a9c146a09505837ec03b2git branch feature-pre-v13# or4git checkout -b feature-pre-v1
git rm
or git reset
they will be in there dangling. Its not easy to find them.1git checkout HEAD -- fn.ext2git checkout -- .3git reset --hard4git clean -f