top
upGrad KnowledgeHut SkillFest Sale!

Search

GIT Tutorial

1. What is a branch and visualize branchesIndependent line of development or parallel development of code along with the main code.Branches are used to develop a new feature or to fix a bug in the code.In other words:Branch is a reference to a commit.cd learn_branching#To visualize the graphical logs for current branchgit log --oneline --graph * dff8df9 (HEAD -> master, origin/master) 2 commit: hello.sh code file added. * 4871096 1 commit: Initial Project structure and Readme file added.#To visualize the graphical logs for all the branchesgit log --graph --oneline --all --decorate--decorate: adds labels to the commits (HEAD, tags, remote branches and local branches)*   277c573 (quickfix, iss53) Merged branch iss53 into quickfix |\   | * 13fbd09 iss53 bug fixed. * | c5487f5 adding quickfix |/   | * dff8df9 (HEAD -> master, origin/master) 2 commit: hello.sh code file added. | | * 7287290 (preprod, development) Adding main function | |/   |/|    | | * 820c0e8 (origin/iss53) end of bug fix.Tested. | | * 1b7283d iss53 bug fixed. | |/   |/|    | | * 43d4441 (tag: new, myProj/master) Update README to version 3.2 | | *   0f491ba (myProj/issue) Merge branch 'master' of https://github.com/greets/myProj | | |\  Set an alias for this command in the config filegit config --global alias.showbranches 'log --graph --oneline --all --decorate' git showbranches2. Create a branchProject: learn_branching--git list branches using the command: git branchDivya1@Divya:learn_branching [master] $git branch  iss53 * master  new-feature  newBranchCreate a new branch from the latest commit--create branch gitgit branch newBranchCreate a branch from an old commitgit branch firstBranch commitIDCreate a branch and jump onto itgit checkout -b quickfix3. Switch between branchesSwitch/jump to the new branchgit checkout newBranchSwitch back to master branchgit checkout master4. What is a merge and its typesMerging together the work of different branches.Git merge branch to another branch.a) Fast-forward merge”feature” or child branch progresses while the “master” or parent branch does not.‘feature’ branch code is merged into ‘master’ branch, that progresses the HEAD of master on to the tip of ‘feature’ branch commit.b) 3-way or recursive mergeThe nomenclature comes from the fact that Git uses three commits to generate the merge commit: the two branch tips and their common ancestor.Diagram: ‘feature’ branch develops after branching out from ‘master’ ‘master’ branch progresses while ‘feature’ branch is under developmentDiagram: ‘feature’ branch merged into ‘master’ As in the case of a fast-forward merge, the tip of both the branches: ‘feature’ and ‘master’ both progresses and points to the same latest commit.c) 3-way merge vs fast-forward git merge demoDemo: Fast-forward mergeStep 1: master history before mergegit hist * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (HEAD -> master, quick_fix) [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 2: Create a ‘quickfix’ branch git checkout -b quickfix * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (HEAD -> master, quick_fix) [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 3: make a single commit in “quickfix” branchecho "quickfix added" > quickfix.file git add . && git commit -m 'Add quickfix code.' ”quickfix” history after making a single commit * 043925a 2018-11-17 | Add quickfix code. (HEAD -> master) [divya bhushan] * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (quick_fix) [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 4: Checkout “master” and merge “quickfix”git checkout master git merge quickfix Updating 5e69ac9..d2eeffd Fast-forward quickfix.file      | 1 + 1 file changed, 1 insertions(+) create mode 100644 quickfix.file #Linear history after the new-feature merge – a fast-forward merge git hist * d2eeffd 2018-11-17 | Add quickfix code. (HEAD -> master, quickfix) [divya bhushan] * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Demo: 3-Way merge: Master progresses while feature is in progressStep 1: Start a ‘new-feature’ branchgit checkout -b new-feature masterStep 2: Make a commitecho "starting new feature">newFeature.txt git add . && git commit -m 'Starting newFeature'Step 3: Make another commitecho "End of new feature">>newFeature.txt git add . && git commit -m 'End of newFeature' * 9926d3b 2018-11-17 | End of newFeature (HEAD -> new-feature) [divya bhushan] * adf9bce 2018-11-17 | Starting newFeature [divya bhushan] * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (master) [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 4: Jump to “master” branch and make commits git checkout master#Open the file for editing using vim in the “ex” mode ex -s -c '2i|main(){' -c x code/hello.sh ex -s -c '4i|}' -c x code/hello.sh c{command}: {command} will be executed after the first file has been read. -s{file}: {file}  will be sourced after the first file has been read. x: Write if changes have been made and exit git add . && git commit -m 'Add main function'Step 5: Merge in the new-feature branchgit merge new-featureMerge made by the 'recursive' strategy.newFeature.txt |  2++1 file changed, 2 insertions(+)create mode 100644 newFeature.txt‘master’ non-linear history after a recursive change*   283c8ba 2018-11-17 | Merge branch 'new-feature' (HEAD -> master) [divya bhushan] |\   | * 9926d3b 2018-11-17 | End of newFeature (new-feature) [divya bhushan] | * adf9bce 2018-11-17 | Starting newFeature [divya bhushan] * | 493d996 2018-11-17 | Add main function [divya bhushan] |/   * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]5. Generate merge conflictsDiffmerge configure:WINDOWS:cd C:/Program Files/SourceGear/Common/DiffMerge/sgdm.exe rename “sgdm.exe” to “diffmerge”MAC:ln -s /Applications/DiffMerge.app/Contents/Resources/diffmerge.sh /usr/local/bin/diffmerge cat /usr/local/bin/diffmergeEdit the global config file and add ‘diffmerge’ as the merging toolgit config --global merge.tool "diffmerge"Run the below command to pass on the file arguments while resolving the conflict.git config --global mergetool.diffmerge.cmd "/usr/local/bin/diffmerge --merge --result=\"\$MERGED\" \"\$LOCAL\" \"\$BASE\" \"\$REMOTE\"" #Generate conflicts between 2 branches: git merge conflictProject: learn_branchingStep 1: make a commit from master branchgit checkout masterEdit the code/hello.sh file#!/bin/sh main(){ echo "Hello $USERNAME !" exit 0 } main $@ git add . && git commit -m 'Add main function' * 6f0f07e 2018-11-19 | Add main function (HEAD -> master) [divya bhushan] * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 2: switch to “iss53” branch and edit the same filegit checkout iss53code/hello.sh original file: #!/bin/sh echo "Hello $USERNAME !" exit 0 vi code/hello.sh #!/bin/sh echo "Hello $USERNAME !" iss53(){        echo "Start of bug fix" } exit 0 git add . && git commit -m 'Start of bug fix.' vi code/hello.sh #!/bin/sh echo "Hello $USERNAME !" iss53(){ echo "Start of bug fix" echo "End of bug fix" } exit 0 git add . && git commit -m 'End of bug fix.' History of ‘iss53’ branch * e2225bb 2018-11-19 | End of bug fix. (HEAD -> iss53) [divya bhushan] * 4258abe 2018-11-19 | Start of bug fix. [divya bhushan] * 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets] * 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]Step 3: Switch to “master” and merge “iss53”git checkout master git merge iss53Auto-merging code/hello.shCONFLICT (content): Merge conflict in code/hello.shAutomatic merge failed; fix conflicts and then commit the result.#master statusgit status On branch master You have unmerged paths.  (fix conflicts and run "git commit")  (use "git merge --abort" to abort the merge) Unmerged paths:  (use "git add <file>..." to mark resolution)       both modified:   code/hello.sh no changes added to commit (use "git add" and/or "git commit -a") Let’s now see how git resolve conflicts. In the next section we will learn how to fix merge conflicts in git.6. Merge tools (diffmerge): resolving conflictLaunch the git auto merge tool:’git mergetool’ to resolve the conflictEdit the BASE file merging the changes from LOCAL (master: left) and REMOTE (iss53: right), save and closeRemove the temporary code/hello.sh.orig file and commit7. Stash changesStashing takes the dirty state (pending work) of your working directory – that is, your modified tracked files and staged changes – and saves it on a stack of unfinished changes that you can reapply at any time.NOTE: By default, git stash will only store files that are already in the “Index” (Staging area).Un-tracked files will be ignored from “stash” command, i.e, will not be stashed.Project: gitRepos/proj_stashgit clone http://github.com/divyabhushan/proj_stash.gita) Stash your workLet’s you stash your dirty working state and continue working on something else.#Jump to “unfinishedWork” branch git checkout unfinishedWork #check the status git statusOn branch unfinishedWorkChanges to be committed: (use "git reset HEAD <file>..." to unstage)       new file:   logs/myLogs.logChanges 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 stash Saved working directory and index state WIP on unfinishedWork: 5707ae7 added index.html and updated README#check the status again, the branch in clean state now On branch unfinishedWork nothing to commit, working tree cleanb) View stashed listgit stash list stash@{0}: WIP on unfinishedWork: 5707ae7 modified readme and deleted upsupported files #To further find out what was done in that stash git show 2a3c789 #To read the commit object git cat-file -p 2a3c789C) Apply stashed changesgit stash apply git stash apply stash@{0} #see the status after applying stash On branch un-finished_work Changes to be committed:  (use "git reset HEAD <file>..." to unstage) new file:   logs/myLogs.log 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    modified:   index.htmld) Create a new branch with the stashed changesgit stash branch pendingWork M README A logs/myLogs.log Switched to a new branch 'pendingWork'e) Delete the saved stashesgit stash drop stash@{index_number} git stash drop stash@{1} Dropped stash@{1} (d1d59b6af3a77782b6c1e4584e42845b51b643d8)8. Branch management in gita) List the branches and see merged/not-mergedcd learn_branchingShow the branches- git list branchesgit branch  iss53 * master  new-feature  old_commit_branch  quick_fixList the branches merged with the current branchgit branch --merged  iss53 * masterList the branches not merged with the current branchbranch --no-merged  new-feature  old_commit_branch  quick_fixb) Rename branchesgit branch -mv iss53 issuec) Delete branches Switch to any other branch other than the one you want to delete--git delete branch or remove branch gitDelete the merged branchgit branch -d branch_nameDelete the un-merged branchgit branch -D branch_name9. Merge branches using git rebasegit-rebase - Reapply commits on top of another base tipquote: (“I want to base my changes on what everybody has already done.” )Usage:git rebase <base>Primary reason:- Maintain a linear project history (in-case of no conflict)- Show my(branch you are rebasing) commits logs on the top not burying them at the last.A “new-feature” developed, rebase will move the “new-feature” to the tip of the “master”.Go back to “master” and do a standard fast-forward merge. Few key differences between git merge and git rebase:git merge applies all unique commits from branch A into branch B in one commit with final resultgit merge doesn’t rewrite commit history, just adds one new commit, unlike rebase which re-writes/re-creates the commit object.git rebase gets all unique commits from both branches and applies them one by one.git rebase rewrites commit history but doesn’t create extra commit for merging (it rearranges the history)in other words: git rebase copies over the commit to a new commit with a different parent and SHA1 id.Project: rebase_project#Project history before a new feature and rebase * 4858dd4 2018-09-22 | Initial project structure. (HEAD -> master, tag: v1.0) [divya]Step 1: Create 2 branches: “dev” and “uat” from “master” also make a commit on “master”git branch dev git branch uat echo "#Author: Divya" >> README.file git add . && git commit -m 'Add author in the README file.' #’master’ history git hist * d2c5ab2 2018-11-20 | Add author in the README file. (HEAD -> master) [divya bhushan] * fd70cb1 2018-10-10 | Initial project structure. (tag: v1.0, dev) [divya bhushan]Step 2: make two commits each from “dev” and “uat” branchesgit checkout dev echo 'Start of dev work' > dev.file git add . && git commit -m 'Start of dev work.' echo 'End of dev work' >> dev.file git add . && git commit -m 'End of dev work.' #’dev’ history * e87c54c 2018-09-22 | End of dev work. (HEAD -> dev) [divya] * 0e4cbf7 2018-09-22 | Start of dev work. [divya] * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya] git checkout uat echo “Start of uat work” > uat.file git add . && git commit -m 'Start of uat work.' echo “Start of uat work” >> uat.file git add . && git commit -m 'End of uat work.' #uat history * 8ff8f4c 2018-09-22 | End of uat work. (HEAD -> uat) [divya] * 18fecd1 2018-09-22 | Start of uat work. [divya] * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]Step 3: merge branch “dev” [recursive merge, non-linear history] and rebase branch “uat” [linear history]git checkout master git merge dev Merge made by the 'recursive' strategy. dev.file | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 dev.file #master history after merging ‘dev’ *   86f521c 2018-09-22 | Merge branch 'dev' (HEAD -> master) [divya] |\   | * e87c54c 2018-09-22 | End of dev work. (dev) [divya] | * 0e4cbf7 2018-09-22 | Start of dev work. [divya] * | 2b142f2 2018-09-22 | Adding author in the main function. [divya] |/   * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya] git checkout uat #’uat’ history before a rebase * 8ff8f4c 2018-09-22 | End of uat work. (HEAD -> uat) [divya] * 18fecd1 2018-09-22 | Start of uat work. [divya] * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya] git rebase master First, rewinding head to replay your work on top of it... Applying: Start of uat work. Applying: End of uat work. #’uat’ history after rebase * 340f107 2018-09-22 | End of uat work. (HEAD -> uat) [divya] * 5a12690 2018-09-22 | Start of uat work. [divya] *   86f521c 2018-09-22 | Merge branch 'dev' (master) [divya] |\   | * e87c54c 2018-09-22 | End of dev work. (dev) [divya] | * 0e4cbf7 2018-09-22 | Start of dev work. [divya] * | 2b142f2 2018-09-22 | Adding author in the main function. [divya] |/   * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]Step 4: jump to “master” branch and merge “uat”git checkout master git merge uat Updating 86f521c..340f107 Fast-forward uat.file | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 uat.fileStep 5: check the master historygit hist * 340f107 2018-09-22 | End of uat work. (HEAD -> master, uat) [divya] * 5a12690 2018-09-22 | Start of uat work. [divya] *   86f521c 2018-09-22 | Merge branch 'dev' [divya] |\   | * e87c54c 2018-09-22 | End of dev work. (dev) [divya] | * 0e4cbf7 2018-09-22 | Start of dev work. [divya] * | 2b142f2 2018-09-22 | Adding author in the main function. [divya] |/   * 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]NOTE: The commit object ids (SHA-1) for the ‘uat’ branch changes, they are re-written…thus losing the original reference. Developers referencing to the old SHA-1 of these ‘uat’ commits will face problems.SHA-1 of ‘dev’ branch have not changed since the original commit ids of ‘dev’ branchIn-case the conflicts are too bad and you wish to go for a normal fast-forward merge, you can easily get out of rebase by typing the command: git rebase --abortSummary:Merging branch ‘dev’ into ‘master’ gives an additional commit id and a curved history, whereas rebasing ‘uat’ into ‘master’ gives no additional commit id and a linear history with ‘uat’ commits as the latest, however re-writes and changes the commit object ids.10. Understand and do a squash mergeWhat is it?--squash flag with the ‘git merge’ combines the commits into a single commit, but do not make a commit.Definition from the man page:--squash: Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit).What it does?This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).Advantage of a ‘squash’ merge:Advantage of a ‘squash’ merge:Neat history and less crowded.‘--squash merge’ in action:git clone http://github.com/divyabhushan/squash_proj.gitcd squash_proj git checkout master branches: 5  bug#1234  dev  master  messy  uatStep 1: Create a ‘messy’ branch from ‘master’ & merge 3 branches: ‘dev’, ‘uat’ and ‘bug#1234’ into it.git checkout -b messy git merge dev uat bug#1234 Fast-forwarding to: dev Trying simple merge with uat Trying simple merge with bug#1234 Merge made by the 'octopus' strategy. bug.fix  | 2 ++ dev.file | 2 ++ uat.file | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 bug.fix create mode 100644 dev.fileShow the commit history of ‘messy’ branchgit log --oneline --decorate –graph *-. a385b07(HEAD->messy) Merge branches 'dev','uat' and 'bug#1234' into messy |\ \   | | * c551404 (origin/bug#1234, bug#1234) Fix the bug#1234 | * | 3edb5dd (origin/uat, uat) End of uat work. | * | be270ff Start of uat work. | |/   * | 060b545 (origin/dev, dev) End of dev work. * | 46e3c6f Start of dev work. |/  * 99caeae (tag: v1.0, origin/sortedCommits, origin/master, sortedCommits, master) Initial project structure.Step 2: Checkout ‘sortedCommits’ branch* 99caeae 2018-11-22 | Initial project structure. (HEAD -> master, tag: v1.0) [divya bhushan] git checkout sortedCommits git hist * 99caeae 2018-11-22 | Initial project structure. (HEAD -> sortedCommits, tag: v1.0, origin/sortedCommits, origin/master, master) [divya bhushan]Merge the ‘messy’ branch with --squash option into ‘sortedCommits’git merge --squash messy Updating 99caeae..a385b07 Fast-forward Squash commit -- not updating HEAD bug.fix  | 2 ++ dev.file | 2 ++ uat.file | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 bug.fix create mode 100644 dev.file create mode 100644 uat.fileCheck the Index area:git status On branch sortedCommits Changes to be committed:  (use "git reset HEAD <file>..." to unstage)      new file:   bug.fix new file:   dev.file       new file:   uat.fileCommit the new merged changes.git commit -m 'Merge uat,dev and bug#1234 into sortedCommits'‘sortedCommits’ branch has the changes from all the 3 branches as a single commit.git hist * c644d76 2018-11-22 | Merge uat,dev and bug#1234 into sortedCommits (HEAD -> sortedCommits) [divya bhushan] * 99caeae 2018-11-22 | Initial project structure. (tag: v1.0, origin/sortedCommits, origin/master, master) [divya bhushan]Summary: - Merging with the --squash flag will update the current branch with the unique commit ids of the merged branch, with a single commit id avoiding all the messes of various merges and conflicts.- merge --squash will not update the HEAD and will not make the commit; but waits for the user to make the commit.Undoing changes(fixing errors) in the working copy and Staging areagit checkout : for a single file or a set of files/directoriesUnstaging files, updating index: git reset (--mixed)a) git checkout : for a single file or a set of files/directoriesChecking out filesChecking out commits(snapshot)Project: viewOldCommitsCheckout the ‘dev’ branch from the repositoryNOTE: We will learn more about remote repository in the upcoming modules.git checkout devUndo 1: Undo an entire snapshot, i.e, get back the old state of a project# View the logs and get the commit id of the snapshot you want to go back toDivya1@Divya:viewOldCommits [dev] $git hist * 6acd128 2018-11-23 | commit:6 - modify file2 (HEAD -> dev, origin/master, origin/dev, origin/HEAD, master) [divya bhushan] * 9ccda28 2018-11-23 | commit:5 - add file5 [divya bhushan] * 6a1dd8f 2018-11-23 | commit:4 - add file4 [divya bhushan] * 81d8ad7 2018-11-23 | commit:3 - add file3 [divya bhushan] * 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 [divya bhushan] * 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]Say, we need to get the old snapshot of the commit-id and get the project as it was at this time:$git checkout 3c6ea80 Note: checking out '3c6ea80'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example:   git checkout -b <new-branch-name> HEAD is now at 3c6ea80 commit:2 - add file2+file22 and edit file1$ls $file1 file2 file22$git hist * 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 (HEAD) [divya bhushan] * 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]Commits only until ‘3c6ea80’ present.Detached HEAD concept:As we learnt that ‘branch’ is a pointer reference to the latest project snapshot.When you jump to an old snapshot (commitId) without creating a branch, the HEAD pointer gets detached from the latest commit id and points to that old commit id that you have checked out; that’s called a Detached HEAD.What do you do here?Get the old version of a Project and make appropriate changes/fixes and commit.How do you save your work?Create a branch from here and switch to that branchgit checkout -b oldState_branch Switched to a new branch 'oldState_branch'Warning:If you switch/jump/checkout to a new branch without saving your work to another branch, you will lose the new commits you made on this ‘Detached HEAD’Edit ‘file1’ and also add a README file in this Project snapshot$echo “version:1.0”>>file1 $echo “readme”>README $git status On branch oldState_branch 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:   file1 Untracked files:  (use "git add <file>..." to include in what will be committed) READMEgit add . && git commit -m 'old checkout: edit file1 and add README'# Switch back to current state (master) and then either revert or commit the old stategit checkout master git merge oldState_branch‘master’ history nowDivya1@Divya:viewOldCommits [master] $git hist *   3e7d43c 2018-11-27 | Merge branch 'oldState_branch' (HEAD -> master) [divya bhushan] |\   | * 87e07d8 2018-11-27 | old checkout: edit file1 and add README (oldState_branch) [divya bhushan] * | 6acd128 2018-11-23 | commit:6 - modify file2 (origin/master, origin/dev, origin/HEAD, dev) [divya bhushan] * | 9ccda28 2018-11-23 | commit:5 - add file5 [divya bhushan] * | 6a1dd8f 2018-11-23 | commit:4 - add file4 [divya bhushan] * | 81d8ad7 2018-11-23 | commit:3 - add file3 [divya bhushan] |/   * 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 [divya bhushan] * 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]SUMMARY:We just fixed the mistake in an old snapshot of the project with commit id: 3c6ea80What did we fix?- Added the version in ‘file1’ + added the README file from another branch ‘oldState_branch’- Merged that forgotten change in the ‘master’ branchUndo 2: Get back an older version of a fileThis affects the current file and file will be listed as modified under the ‘Staging area’Scenario:You forgot to add a piece of code in your script.Step 1: Switch to ‘dev’ branch and get the older version of ‘file1’ from an old commitgit checkout dev cat file2filename: file2 Edit the file. version:1.0git checkout 3c6ea80 file2 cat file2 filename: file2Step 2: Edit this old version of the file and make a new commit.echo "author:authorName">>file2 git add . git commit -m 'add older version of file2, after edit'Step 3: You could merge the older version of ‘file2’ into ‘uat’ branchecho "author:authorName">>file2 git add . git commit -m 'add older version of file2, after edit'git checkout uat git merge devResolve conflict and mergegit mergetoolMerge the changes from ‘dev’ first and then ‘uat’git merge --continue rm file2.orgSummary:We checked out an older version of ‘file2’ from ‘dev’ branch, made edits and merged that change with the latest ‘file2’ on ‘uat’ branch.You may further merge this change with ‘master’ branch as well.b) Un-stage files, update index: git reset (--mixed)Say you want to un-stage certain files that you accidentally added to the Index, run the below command:git resetgit reset --mixed git reset --mixed will unstage the files respectively, working directory will not be affectedProject : viewOldCommitsStep 1: Add new files and modify an existing file from the ‘preprod’ branchgit checkout preprod mkdir code vi code/mycode.sh #!/bin/sh echo "Hello $USER" touch db.err db.log echo “version:1.0”>>README rm file5 git status git add --allChanges to be committed:  (use "git reset HEAD <file>..." to unstage) modified:   README new file:   code/mycode.sh new file:   db.err     new file:   db.log    deleted:    file5To un-stage the entire snapshot of the project:$git reset HEAD $git status 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          deleted:   file5 Untracked files:  (use "git add <file>..." to include in what will be committed) code/ db.err db.log no changes added to commit (use "git add" and/or "git commit -a")Add all the files back to ‘Index’git add --allTo un-stage a single filegit reset HEAD db.errChanges to be committed:  (use "git reset HEAD <file>..." to unstage)         modified:   README new file:   code/mycode.sh new file:   db.log         deleted:    file5 Untracked files:  (use "git add <file>..." to include in what will be committed) db.errThe file ‘db.err’ has only been Un-staged as being to an ‘untracked’ file, and still present in your working directory.Deleted file is still deleted but that change is un-staged.New files added will be un-trackedModified file is still modified, again the change is un-staged… working dir is not affected.git add --all git commit -m ‘Random changes to learn git reset --mixed’12. Undoing/redoing changes in the repository historya) Amend just the latest commit object/history: git commit –amendProject: reset_projectgit checkout branch1 git hist* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch1, origin/master, origin/branch1, master) [divya] * 9429703 2018-08-18 | v3: main function added [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]Edit just the latest commit message.git commit --amend -m 'v4: Add sub-functions' git status* cb9dba4 2018-08-18 | v4: Add sub-functions (HEAD -> branch1) [divya] * 9429703 2018-08-18 | v3: main function added [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]Note: Commit id changes from ‘5fa64c6’ to ‘cb9dba4’.No new commit is created.Summary:We only edited the commit message with no change in the files(Working directory) or the Index.Just the commit history changes with a new commit object.Do not: amend the commits that are already pushed and present in a remote shared repository.Another way:Say you forgot to add/modify/delete a file before making the last commit.git checkout branch2 echo “author:Name”>>README touch database.log git add --all git statusOn branch branch2 Your branch is up to date with 'origin/branch2'. Changes to be committed:  (use "git reset HEAD <file>..." to unstage)         modified:   README         new file:   database.logLatest commit on ‘branch2’ before amending* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch2, origin/master, origin/branch2, origin/branch1, master) [divya]git commit --amend v4: Add sub-functions, modified README, added database.log[branch2 c0ebb4f] v4: Add sub-functions, modified README, added database.log Date: Sat Aug 18 16:45:19 2018 +0530 3 files changed, 8 insertions(+) create mode 100644 database.log* c0ebb4f 2018-08-18 | v4: Add sub-functions, modified README, added database.log (HEAD -> branch2) [divya]Commit id changed from ‘5fa64c6’ to ‘c0ebb4f’.b) Reset the commits in the local repository: git reset –-softThis command will reset the HEAD pointer to the commit id mentioned by the command.Will not modify the files either in the Index or Working directory.Project: reset_projectgit checkout branch3 git hist* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch3, origin/master, origin/branch3, origin/branch2, origin/branch1, master, branch2) [divya] * 9429703 2018-08-18 | v3: main function added [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]git reset --soft HEAD~1Local history changed after the ‘reset’, You could modify the project and recommit.* 9429703 2018-08-18 | v3: main function added (HEAD -> branch3) [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]The file that was committed in the latest commit has been put back in Index; waiting to be committed.NOTE: The ‘Staging area’ has not been affected as the file has not been un-staged.git hist Changes to be committed:  (use "git reset HEAD <file>..." to unstage)         modified:   main.funcHow will this help?You could delete the bad commit; could modify/add/delete the project code and re-commit.Summary: ‘git reset --soft' resets the local history allowing you to re-write the project history.‘Index’ and ‘Working dir’ not affected.Try also:You can also reset the local history to any previous commit id.git checkout branch4 git hist* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch4, origin/master, origin/branch4, origin/branch3, origin/branch2, origin/branch1, master, branch3, branch2) [divya] * 9429703 2018-08-18 | v3: main function added [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]History is reset to the first initial commit.* 7558269 2018-08-18 | v1: Initial file added (HEAD -> branch4) [divya]Latest project snapshot upto the commit id:‘7558269’ have been un-committed.$git status Changes to be committed:  (use "git reset HEAD <file>..." to unstage) new file:   README modified:   main.funcc) Reset to sync Working dir, Staging area and Local repository: git reset –-hardgit reset --hard commit-id git reset --hard HEAD~1 git reset --hard HEAD~3Permanent undo – lose your workUsed to:a. Remove committed snapshotsb.Undo changes in staging area and working directoryUse it:only to undo local changesDo not use:To reset snapshots that have been shared with othersDiagram: The 3 states of the project and the effect of reset Its history is same as the previous branches and ‘master’Make a new commit and check history$echo "database log file.">db.log $git add . && git commit -m 'Add db.log' $git hist * 9eb255a 2018-12-03 | Add db.log (HEAD -> branch5) [divya] * 5fa64c6 2018-08-18 | v4: sub-functions added (origin/master, origin/branch5, origin/branch4, origin/branch3, origin/branch2, origin/branch1, master, branch4, branch3, branch2) [divya] * 9429703 2018-08-18 | v3: main function added [divya] * 4dcbe20 2018-08-18 | v2: README file added [divya] * 7558269 2018-08-18 | v1: Initial file added [divya]Undo the last commit that you made by mistake; reset to 1 previous commit pointed by HEADgit reset --hard HEAD~1 HEAD is now at 5fa64c6 v4: sub-functions addedNOTE:‘db.log’ file would be gone and the history will be reset back to commit id: ‘5fa64c6’To reset to earlier named commit ids, you could also run as below:git reset --hard HEAD~3 OR git reset --hard 4dcbe2013. Revert a committed snapshot or revert an old file: gitgit revert is used to record some new commits to reverse the effect of some earlier commits/snapshot of a project.Instead of removing the commit from the project history, it figures out how to undo the changes introduced by the commit & appends a new commit with the resulting content in the current branch.Usage: git revert <commit_id>Use: To undo an entire commit from your project history; removing a bug introduced by a commit.Reset Vs Revertgit “reset”: resets the project to a previous snapshot erasing the changes.git “revert” does not change the project history unlike git “reset”Git “revert” undoes the commit id changes and applies the undo work as a new commit id object.Undo 1: Revert the recent commitProject: revert_ExampleLatest commit history$git hist * b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (HEAD -> master, origin/master, test) [greets] * 657c0d8 2015-07-29 | 3rd commit: file3 added, readme added [greets] * fbd89be 2015-07-29 | 2nd commit: file1 deleted, file2 added [greets] * f9deb74 2015-07-29 | 1st commit: file1 added [greets]’Working dir’ before a revertfile2.txt file4.txt flie3.txt library.lib readme.txtgit revert HEAD #edit the message in the editor if needed.[master 81880fa] Revert "4th commit: added file4, library.lib and modified readme." 3 files changed, 2 deletions(-) delete mode 100644 file4.txt delete mode 100644 library.lib#History remains the same, new commit id added with reverted changes$git hist * 81880fa 2018-12-03 | Revert "4th commit: added file4, library.lib and modified readme." (HEAD -> master) [divya bhushan] * b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (origin/master, test) [greets] * 657c0d8 2015-07-29 | 3rd commit: file3 added, readme added [greets] * fbd89be 2015-07-29 | 2nd commit: file1 deleted, file2 added [greets] * f9deb74 2015-07-29 | 1st commit: file1 added [greets]Working dir after revert$git ls file2.txt flie3.txt readme.txtUndo 2: Revert an old commitConsider the same master branch with the latest revert commit we just made.Let’s revert the ‘fbd89be’ commit changes’Working dir’ before a revertls file2.txt flie3.txt readme.txtCheck what was committed in this commitIdgit show fbd89be commit fbd89be6833556c57575fe4838eab0af15b56ee4 Author: greets <greetybhatnagar@gmail.com> Date:   Wed Jul 29 11:29:29 2015 +0530               2nd commit: file1 deleted, file2 added diff --git a/file1.txt b/file2.txt similarity index 100% rename from file1.txt rename to file2.txt‘file1.txt’ was renamed to ‘file2.txt’. Let’s revert this change.git revert fbd89be[master 009612f] Revert "2nd commit: file1 deleted, file2 added" 1 file changed, 0 insertions(+), 0 deletions(-) rename file2.txt => file1.txt (100%)’Working dir’ after revertfile1.txt flie3.txt readme.txtThe reverted commit still remains in the history and a new reverted commit object is added.* 009612f 2018-12-03 | Revert "2nd commit: file1 deleted, file2 added" (HEAD -> master) [divya bhushan] * 81880fa 2018-12-03 | Revert "4th commit: added file4, library.lib and modified readme." [divya bhushan] * b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (origin/master, test) [greets] ……
logo

GIT Tutorial

Branching and Merging

1. What is a branch and visualize branches

Independent line of development or parallel development of code along with the main code.

Branches are used to develop a new feature or to fix a bug in the code.

In other words:

Branch is a reference to a commit.

cd learn_branching

#To visualize the graphical logs for current branch

git log --oneline --graph
* dff8df9 (HEAD -> master, origin/master) 2 commit: hello.sh code file added.
* 4871096 1 commit: Initial Project structure and Readme file added.

#To visualize the graphical logs for all the branches

git log --graph --oneline --all --decorate

--decorate: adds labels to the commits (HEAD, tags, remote branches and local branches)

*   277c573 (quickfix, iss53) Merged branch iss53 into quickfix
|\  
| * 13fbd09 iss53 bug fixed.
* | c5487f5 adding quickfix
|/  
| * dff8df9 (HEAD -> master, origin/master) 2 commit: hello.sh code file added.
| | * 7287290 (preprod, development) Adding main function
| |/  
|/|   
| | * 820c0e8 (origin/iss53) end of bug fix.Tested.
| | * 1b7283d iss53 bug fixed.
| |/  
|/|   
| | * 43d4441 (tag: new, myProj/master) Update README to version 3.2
| | *   0f491ba (myProj/issue) Merge branch 'master' of https://github.com/greets/myProj
| | |\  

Set an alias for this command in the config file

git config --global alias.showbranches 'log --graph --oneline --all --decorate'
git showbranches

2. Create a branch

Project: learn_branching

--git list branches using the command: git branch

Divya1@Divya:learn_branching [master] $git branch
 iss53
* master
 new-feature
 newBranch

Create a new branch from the latest commit

--create branch git

git branch newBranch

Create a branch from an old commit

git branch firstBranch commitID

Create a branch and jump onto it

git checkout -b quickfix

3. Switch between branches

Switch/jump to the new branch

git checkout newBranch

Switch back to master branch

git checkout master

4. What is a merge and its types

Merging together the work of different branches.

Git merge branch to another branch.

a) Fast-forward merge

”feature” or child branch progresses while the “master” or parent branch does not.

Before Merging and After a Fast-Forward Merge

‘feature’ branch code is merged into ‘master’ branch, that progresses the HEAD of master on to the tip of ‘feature’ branch commit.

b) 3-way or recursive merge

The nomenclature comes from the fact that Git uses three commits to generate the merge commit: the two branch tips and their common ancestor.

feature’ branch develops after branching out from ‘master’

Diagram: ‘feature’ branch develops after branching out from ‘master’ 

‘master’ branch progresses while ‘feature’ branch is under development

‘feature’ branch merged into ‘master’

Diagram: ‘feature’ branch merged into ‘master’ 

As in the case of a fast-forward merge, the tip of both the branches: ‘feature’ and ‘master’ both progresses and points to the same latest commit.

c) 3-way merge vs fast-forward git merge demo

Demo: Fast-forward merge

Step 1: master history before merge

git hist
5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (HEAD -> master, quick_fix) [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 2: Create a ‘quickfix’ branch 

git checkout -b quickfix
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (HEAD -> master, quick_fix) [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 3: make a single commit in “quickfix” branch

echo "quickfix added" > quickfix.file
git add . && git commit -m 'Add quickfix code.'
”quickfix” history after making a single commit
043925a 2018-11-17 | Add quickfix code. (HEAD -> master) [divya bhushan]
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (quick_fix) [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 4: Checkout “master” and merge “quickfix”

git checkout master
git merge quickfix
Updating 5e69ac9..d2eeffd
Fast-forward
quickfix.file      | 1 +
1 file changed, 1 insertions(+)
create mode 100644 quickfix.file

#Linear history after the new-feature merge – a fast-forward merge
git hist
* d2eeffd 2018-11-17 | Add quickfix code. (HEAD -> master, quickfix) [divya bhushan]
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Demo: 3-Way merge: Master progresses while feature is in progress

Step 1: Start a ‘new-feature’ branch

git checkout -b new-feature master

Step 2: Make a commit

echo "starting new feature">newFeature.txt
git add . && git commit -m 'Starting newFeature'

Step 3: Make another commit

echo "End of new feature">>newFeature.txt
git add . && git commit -m 'End of newFeature'

* 9926d3b 2018-11-17 | End of newFeature (HEAD -> new-feature) [divya bhushan]
* adf9bce 2018-11-17 | Starting newFeature [divya bhushan]
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. (master) [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 4: Jump to “master” branch and make commits 

git checkout master

#Open the file for editing using vim in the “ex” mode
ex -s -c '2i|main(){' -c x code/hello.sh

ex -s -c '4i|}' -c x code/hello.sh
c{command}: {command} will be executed after the first file has been read.
-s{file}: {file}  will be sourced after the first file has been read.
x: Write if changes have been made and exit
git add . && git commit -m 'Add main function'

Step 5: Merge in the new-feature branch

git merge new-feature

Merge made by the 'recursive' strategy.

newFeature.txt |  2++

1 file changed, 2 insertions(+)

create mode 100644 newFeature.txt

‘master’ non-linear history after a recursive change

*   283c8ba 2018-11-17 | Merge branch 'new-feature' (HEAD -> master) [divya bhushan]
|\  
| * 9926d3b 2018-11-17 | End of newFeature (new-feature) [divya bhushan]
| * adf9bce 2018-11-17 | Starting newFeature [divya bhushan]
* | 493d996 2018-11-17 | Add main function [divya bhushan]
|/  
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

5. Generate merge conflicts

Diffmerge configure:

WINDOWS:

cd C:/Program Files/SourceGear/Common/DiffMerge/sgdm.exe
rename “sgdm.exe” to “diffmerge”

MAC:

ln -s /Applications/DiffMerge.app/Contents/Resources/diffmerge.sh /usr/local/bin/diffmerge
cat /usr/local/bin/diffmerge

Edit the global config file and add ‘diffmerge’ as the merging tool

git config --global merge.tool "diffmerge"

Run the below command to pass on the file arguments while resolving the conflict.

git config --global mergetool.diffmerge.cmd "/usr/local/bin/diffmerge --merge --result=\"\$MERGED\" \"\$LOCAL\" \"\$BASE\" \"\$REMOTE\""
#Generate conflicts between 2 branches: git merge conflict

Project: learn_branching

Step 1: make a commit from master branch

git checkout master

Edit the code/hello.sh file

#!/bin/sh
main(){
echo "Hello $USERNAME !"
exit 0
}
main $@

git add . && git commit -m 'Add main function'
* 6f0f07e 2018-11-19 | Add main function (HEAD -> master) [divya bhushan]
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 2: switch to “iss53” branch and edit the same file

git checkout iss53
code/hello.sh original file:
#!/bin/sh
echo "Hello $USERNAME !"
exit 0

vi code/hello.sh
#!/bin/sh
echo "Hello $USERNAME !"
iss53(){
       echo "Start of bug fix"
}
exit 0
git add . && git commit -m 'Start of bug fix.'

vi code/hello.sh
#!/bin/sh
echo "Hello $USERNAME !"
iss53(){
echo "Start of bug fix"
echo "End of bug fix"
}
exit 0

git add . && git commit -m 'End of bug fix.'

History of ‘iss53’ branch
* e2225bb 2018-11-19 | End of bug fix. (HEAD -> iss53) [divya bhushan]
* 4258abe 2018-11-19 | Start of bug fix. [divya bhushan]
* 5e69ac9 2015-11-26 | 2 commit: hello.sh code file added. [greets]
* 4871096 2015-11-26 | 1 commit: Initial Project structure and Readme file added. [greets]

Step 3: Switch to “master” and merge “iss53”

git checkout master
git merge iss53

Auto-merging code/hello.sh

CONFLICT (content): Merge conflict in code/hello.sh

Automatic merge failed; fix conflicts and then commit the result.

#master status

git status
On branch master
You have unmerged paths.
 (fix conflicts and run "git commit")
 (use "git merge --abort" to abort the merge)
Unmerged paths:
 (use "git add <file>..." to mark resolution)
      both modified:   code/hello.sh
no changes added to commit (use "git add" and/or "git commit -a")

Let’s now see how git resolve conflicts.
In the next section we will learn how to fix merge conflicts in git.

6. Merge tools (diffmerge): resolving conflict

  • Launch the git auto merge tool:’git mergetool’ to resolve the conflict
  • Edit the BASE file merging the changes from LOCAL (master: left) and REMOTE (iss53: right), save and close
  • Remove the temporary code/hello.sh.orig file and commit

7. Stash changes

Stashing takes the dirty state (pending work) of your working directory – that is, your modified tracked files and staged changes – and saves it on a stack of unfinished changes that you can reapply at any time.

NOTE: By default, git stash will only store files that are already in the “Index” (Staging area).

Un-tracked files will be ignored from “stash” command, i.e, will not be stashed.

Project: gitRepos/proj_stash

git clone http://github.com/divyabhushan/proj_stash.git

a) Stash your work

Let’s you stash your dirty working state and continue working on something else.

#Jump to “unfinishedWork” branch
git checkout unfinishedWork

#check the status
git status

On branch unfinishedWork

Changes to be committed:

 (use "git reset HEAD <file>..." to unstage)
      new file:   logs/myLogs.log

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 stash
Saved working directory and index state WIP on unfinishedWork: 5707ae7 added index.html and updated README
#check the status again, the branch in clean state now
On branch unfinishedWork
nothing to commit, working tree clean

b) View stashed list

git stash list
stash@{0}: WIP on unfinishedWork: 5707ae7 modified readme and deleted upsupported files

#To further find out what was done in that stash
git show 2a3c789

#To read the commit object
git cat-file -p 2a3c789

C) Apply stashed changes

git stash apply
git stash apply stash@{0}

#see the status after applying stash
On branch un-finished_work
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

new file:   logs/myLogs.log

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
   modified:   index.html

d) Create a new branch with the stashed changes

git stash branch pendingWork
M README
A logs/myLogs.log
Switched to a new branch 'pendingWork'

e) Delete the saved stashes

git stash drop stash@{index_number}
git stash drop stash@{1}
Dropped stash@{1} (d1d59b6af3a77782b6c1e4584e42845b51b643d8)

8. Branch management in git

a) List the branches and see merged/not-merged

cd learn_branching
  • Show the branches- git list branches
git branch
 iss53
* master
 new-feature
 old_commit_branch
 quick_fix

List the branches merged with the current branch

git branch --merged
 iss53
* master

List the branches not merged with the current branch

branch --no-merged
 new-feature
 old_commit_branch
 quick_fix

b) Rename branches

git branch -mv iss53 issue

c) Delete branches 

Switch to any other branch other than the one you want to delete
--git delete branch or remove branch git
Delete the merged branch

git branch -d branch_name

Delete the un-merged branch

git branch -D branch_name

9. Merge branches using git rebase

git-rebase - Reapply commits on top of another base tip

quote: (“I want to base my changes on what everybody has already done.” )

Brand New Commits

Usage:

git rebase <base>

Primary reason:

- Maintain a linear project history (in-case of no conflict)

- Show my(branch you are rebasing) commits logs on the top not burying them at the last.

Merge branches using git rebaseA “new-feature” developed, rebase will move the “new-feature” to the tip of the “master”.

Go back to “master” and do a standard fast-forward merge.

After Rebasing Onto Master

After a fast-Forward Merge

 

Few key differences between git merge and git rebase:

  • git merge applies all unique commits from branch A into branch B in one commit with final result
  • git merge doesn’t rewrite commit history, just adds one new commit, unlike rebase which re-writes/re-creates the commit object.
  • git rebase gets all unique commits from both branches and applies them one by one.
  • git rebase rewrites commit history but doesn’t create extra commit for merging (it rearranges the history)

in other words: git rebase copies over the commit to a new commit with a different parent and SHA1 id.

Project: rebase_project

#Project history before a new feature and rebase
* 4858dd4 2018-09-22 | Initial project structure. (HEAD -> master, tag: v1.0) [divya]

Step 1: Create 2 branches: “dev” and “uat” from “master” also make a commit on “master”

git branch dev
git branch uat

echo "#Author: Divya" >> README.file
git add . && git commit -m 'Add author in the README file.'
#’master’ history
git hist

* d2c5ab2 2018-11-20 | Add author in the README file. (HEAD -> master) [divya bhushan]
* fd70cb1 2018-10-10 | Initial project structure. (tag: v1.0, dev) [divya bhushan]

Step 2: make two commits each from “dev” and “uat” branches

git checkout dev
echo 'Start of dev work' > dev.file
git add . && git commit -m 'Start of dev work.'

echo 'End of dev work' >> dev.file
git add . && git commit -m 'End of dev work.'
#’dev’ history
* e87c54c 2018-09-22 | End of dev work. (HEAD -> dev) [divya]
* 0e4cbf7 2018-09-22 | Start of dev work. [divya]
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

git checkout uat
echo “Start of uat work” > uat.file
git add . && git commit -m 'Start of uat work.'

echo “Start of uat work” >> uat.file
git add . && git commit -m 'End of uat work.'

#uat history
* 8ff8f4c 2018-09-22 | End of uat work. (HEAD -> uat) [divya]
* 18fecd1 2018-09-22 | Start of uat work. [divya]
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

Step 3: merge branch “dev” [recursive merge, non-linear history] and rebase branch “uat” [linear history]

git checkout master
git merge dev

Merge made by the 'recursive' strategy.
dev.file | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 dev.file

#master history after merging ‘dev’
*   86f521c 2018-09-22 | Merge branch 'dev' (HEAD -> master) [divya]
|\  
| * e87c54c 2018-09-22 | End of dev work. (dev) [divya]
| * 0e4cbf7 2018-09-22 | Start of dev work. [divya]
* | 2b142f2 2018-09-22 | Adding author in the main function. [divya]
|/  
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

git checkout uat

#’uat’ history before a rebase
* 8ff8f4c 2018-09-22 | End of uat work. (HEAD -> uat) [divya]
* 18fecd1 2018-09-22 | Start of uat work. [divya]
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

git rebase master
First, rewinding head to replay your work on top of it...
Applying: Start of uat work.
Applying: End of uat work.

#’uat’ history after rebase

* 340f107 2018-09-22 | End of uat work. (HEAD -> uat) [divya]
* 5a12690 2018-09-22 | Start of uat work. [divya]
*   86f521c 2018-09-22 | Merge branch 'dev' (master) [divya]
|\  
| * e87c54c 2018-09-22 | End of dev work. (dev) [divya]
| * 0e4cbf7 2018-09-22 | Start of dev work. [divya]
* | 2b142f2 2018-09-22 | Adding author in the main function. [divya]
|/  
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

Step 4: jump to “master” branch and merge “uat”

git checkout master
git merge uat
Updating 86f521c..340f107
Fast-forward
uat.file | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 uat.file

Step 5: check the master history

git hist
* 340f107 2018-09-22 | End of uat work. (HEAD -> master, uat) [divya]
* 5a12690 2018-09-22 | Start of uat work. [divya]
*   86f521c 2018-09-22 | Merge branch 'dev' [divya]
|\  
| * e87c54c 2018-09-22 | End of dev work. (dev) [divya]
| * 0e4cbf7 2018-09-22 | Start of dev work. [divya]
* | 2b142f2 2018-09-22 | Adding author in the main function. [divya]
|/  
* 4858dd4 2018-09-22 | Initial project structure. (tag: v1.0) [divya]

NOTE: 

  1. The commit object ids (SHA-1) for the ‘uat’ branch changes, they are re-written…thus losing the original reference. Developers referencing to the old SHA-1 of these ‘uat’ commits will face problems.
  2. SHA-1 of ‘dev’ branch have not changed since the original commit ids of ‘dev’ branch
  3. In-case the conflicts are too bad and you wish to go for a normal fast-forward merge, you can easily get out of rebase by typing the command: git rebase --abort

Summary:
Merging branch ‘dev’ into ‘master’ gives an additional commit id and a curved history, whereas rebasing ‘uat’ into ‘master’ gives no additional commit id and a linear history with ‘uat’ commits as the latest, however re-writes and changes the commit object ids.

10. Understand and do a squash merge

What is it?

--squash flag with the ‘git merge’ combines the commits into a single commit, but do not make a commit.

Definition from the man page:

--squash: Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit).

What it does?

This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).

Advantage of a ‘squash’ merge:

Advantage of a ‘squash’ merge:

Neat history and less crowded.

‘--squash merge’ in action:

git clone http://github.com/divyabhushan/squash_proj.git

cd squash_proj
git checkout master
branches: 5
 bug#1234
 dev
 master
 messy
 uat

Step 1: Create a ‘messy’ branch from ‘master’ & merge 3 branches: ‘dev’, ‘uat’ and ‘bug#1234’ into it.

git checkout -b messy

git merge dev uat bug#1234
Fast-forwarding to: dev
Trying simple merge with uat
Trying simple merge with bug#1234
Merge made by the 'octopus' strategy.
bug.fix  | 2 ++
dev.file | 2 ++
uat.file | 2 ++
3 files changed, 6 insertions(+)
create mode 100644 bug.fix
create mode 100644 dev.file

Show the commit history of ‘messy’ branch

git log --oneline --decorate –graph
*-. a385b07(HEAD->messy) Merge branches 'dev','uat' and 'bug#1234' into messy
|\ \  
| | * c551404 (origin/bug#1234, bug#1234) Fix the bug#1234
| * | 3edb5dd (origin/uat, uat) End of uat work.
| * | be270ff Start of uat work.
| |/  
* | 060b545 (origin/dev, dev) End of dev work.
* | 46e3c6f Start of dev work.
|/  * 99caeae (tag: v1.0, origin/sortedCommits, origin/master, sortedCommits, master) Initial project structure.

Step 2: Checkout ‘sortedCommits’ branch

* 99caeae 2018-11-22 | Initial project structure. (HEAD -> master, tag: v1.0) [divya bhushan]
git checkout sortedCommits
git hist
* 99caeae 2018-11-22 | Initial project structure. (HEAD -> sortedCommits, tag: v1.0, 
origin/sortedCommits, origin/master, master) [divya bhushan]

Merge the ‘messy’ branch with --squash option into ‘sortedCommits’

git merge --squash messy

Updating 99caeae..a385b07
Fast-forward
Squash commit -- not updating HEAD
bug.fix  | 2 ++
dev.file | 2 ++
uat.file | 2 ++
3 files changed, 6 insertions(+)
create mode 100644 bug.fix
create mode 100644 dev.file
create mode 100644 uat.file

Check the Index area:

git status
On branch sortedCommits
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)
      new file:   bug.fix
      new file:   dev.file
      new file:   uat.file

Commit the new merged changes.

git commit -m 'Merge uat,dev and bug#1234 into sortedCommits'

‘sortedCommits’ branch has the changes from all the 3 branches as a single commit.

git hist
* c644d76 2018-11-22 | Merge uat,dev and bug#1234 into sortedCommits (HEAD -> sortedCommits) [divya bhushan]
* 99caeae 2018-11-22 | Initial project structure. (tag: v1.0, origin/sortedCommits, origin/master, master) [divya bhushan]

Summary: 

- Merging with the --squash flag will update the current branch with the unique commit ids of the merged branch, with a single commit id avoiding all the messes of various merges and conflicts.

- merge --squash will not update the HEAD and will not make the commit; but waits for the user to make the commit.

  • Undoing changes(fixing errors) in the working copy and Staging area
    • git checkout : for a single file or a set of files/directories
    • Unstaging files, updating index: git reset (--mixed)

a) git checkoutfor a single file or a set of files/directories

  • Checking out files
  • Checking out commits(snapshot)

ProjectviewOldCommits

Checkout the ‘dev’ branch from the repository

NOTE: We will learn more about remote repository in the upcoming modules.

git checkout dev

Undo 1: Undo an entire snapshot, i.e, get back the old state of a project

# View the logs and get the commit id of the snapshot you want to go back to

Divya1@Divya:viewOldCommits [dev] $git hist
* 6acd128 2018-11-23 | commit:6 - modify file2 (HEAD -> dev, origin/master, origin/dev, origin/HEAD, master) [divya bhushan]
* 9ccda28 2018-11-23 | commit:5 - add file5 [divya bhushan]
* 6a1dd8f 2018-11-23 | commit:4 - add file4 [divya bhushan]
* 81d8ad7 2018-11-23 | commit:3 - add file3 [divya bhushan]
* 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 [divya bhushan]
* 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]

Say, we need to get the old snapshot of the commit-id and get the project as it was at this time:

$git checkout 3c6ea80

Note: checking out '3c6ea80'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
  git checkout -b <new-branch-name>
HEAD is now at 3c6ea80 commit:2 - add file2+file22 and edit file1

$ls
$file1  file2  file22

$git hist
* 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 (HEAD) [divya bhushan]
* 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]

Commits only until ‘3c6ea80’ present.

Detached HEAD concept:

  • As we learnt that ‘branch’ is a pointer reference to the latest project snapshot.
  • When you jump to an old snapshot (commitId) without creating a branch, the HEAD pointer gets detached from the latest commit id and points to that old commit id that you have checked out; that’s called a Detached HEAD.

What do you do here?

Get the old version of a Project and make appropriate changes/fixes and commit.

How do you save your work?

Create a branch from here and switch to that branch

git checkout -b oldState_branch
Switched to a new branch 'oldState_branch'

Warning:

If you switch/jump/checkout to a new branch without saving your work to another branch, you will lose the new commits you made on this ‘Detached HEAD’

Edit ‘file1’ and also add a README file in this Project snapshot

$echo “version:1.0”>>file1
$echo “readme”>README

$git status
On branch oldState_branch
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:   file1

Untracked files:
 (use "git add <file>..." to include in what will be committed)
README

git add . && git commit -m 'old checkout: edit file1 and add README'

# Switch back to current state (master) and then either revert or commit the old state

git checkout master
git merge oldState_branch

‘master’ history now

Divya1@Divya:viewOldCommits [master] $git hist
*   3e7d43c 2018-11-27 | Merge branch 'oldState_branch' (HEAD -> master) [divya bhushan]
|\  
| * 87e07d8 2018-11-27 | old checkout: edit file1 and add README (oldState_branch) [divya bhushan]
* | 6acd128 2018-11-23 | commit:6 - modify file2 (origin/master, origin/dev, origin/HEAD, dev) [divya bhushan]
* | 9ccda28 2018-11-23 | commit:5 - add file5 [divya bhushan]
* | 6a1dd8f 2018-11-23 | commit:4 - add file4 [divya bhushan]
* | 81d8ad7 2018-11-23 | commit:3 - add file3 [divya bhushan]
|/  
* 3c6ea80 2018-11-23 | commit:2 - add file2+file22 and edit file1 [divya bhushan]
* 47a35bc 2018-11-23 | commit:1 - add file1 [divya bhushan]

SUMMARY:

We just fixed the mistake in an old snapshot of the project with commit id: 3c6ea80

What did we fix?
- Added the version in ‘file1’ + added the README file from another branch ‘oldState_branch’

- Merged that forgotten change in the ‘master’ branch

Undo 2: Get back an older version of a file

This affects the current file and file will be listed as modified under the ‘Staging area’

Scenario:

You forgot to add a piece of code in your script.

Step 1: Switch to ‘dev’ branch and get the older version of ‘file1’ from an old commit

git checkout dev

cat file2

filename: file2
Edit the file.
version:1.0

git checkout 3c6ea80 file2

cat file2
filename: file2

Step 2: Edit this old version of the file and make a new commit.

echo "author:authorName">>file2
git add .
git commit -m 'add older version of file2, after edit'

Step 3: You could merge the older version of ‘file2’ into ‘uat’ branch

echo "author:authorName">>file2
git add .
git commit -m 'add older version of file2, after edit'

git checkout uat
git merge dev

Resolve conflict and merge

git mergetool

Merge the changes from ‘dev’ first and then ‘uat’

git merge --continue
rm file2.org

Summary:

We checked out an older version of ‘file2’ from ‘dev’ branch, made edits and merged that change with the latest ‘file2’ on ‘uat’ branch.

You may further merge this change with ‘master’ branch as well.

b) Un-stage files, update index: git reset (--mixed)

Say you want to un-stage certain files that you accidentally added to the Index, run the below command:

git reset

git reset --mixed 

git reset --mixed will unstage the files respectively, working directory will not be affected

Project : viewOldCommits

Step 1: Add new files and modify an existing file from the ‘preprod’ branch

git checkout preprod

mkdir code
vi code/mycode.sh
#!/bin/sh
echo "Hello $USER"

touch db.err db.log

echo “version:1.0”>>README

rm file5

git status

git add --all

Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)
modified:   README
new file:   code/mycode.sh
new file:   db.err
    new file:   db.log
   deleted:    file5

To un-stage the entire snapshot of the project:

$git reset HEAD
$git status
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
         deleted:   file5

Untracked files:
 (use "git add <file>..." to include in what will be committed)

code/
db.err
db.log

no changes added to commit (use "git add" and/or "git commit -a")

Add all the files back to ‘Index’

git add --all

To un-stage a single file

git reset HEAD db.err

Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

        modified:   README
        new file:   code/mycode.sh
        new file:   db.log
        deleted:    file5

Untracked files:
 (use "git add <file>..." to include in what will be committed)
db.err

The file ‘db.err’ has only been Un-staged as being to an ‘untracked’ file, and still present in your working directory.

  • Deleted file is still deleted but that change is un-staged.
  • New files added will be un-tracked
  • Modified file is still modified, again the change is un-staged… working dir is not affected.

git add --all
git commit -m ‘Random changes to learn git reset --mixed’

12. Undoing/redoing changes in the repository history

a) Amend just the latest commit object/history: git commit –amend

Project: reset_project

git checkout branch1

git hist

* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch1, origin/master, origin/branch1, master) [divya]
* 9429703 2018-08-18 | v3: main function added [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

Edit just the latest commit message.

git commit --amend -m 'v4: Add sub-functions'

git status

* cb9dba4 2018-08-18 | v4: Add sub-functions (HEAD -> branch1) [divya]
* 9429703 2018-08-18 | v3: main function added [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

Note: 
Commit id changes from ‘5fa64c6’ to ‘cb9dba4’.

No new commit is created.

Summary:

We only edited the commit message with no change in the files(Working directory) or the Index.

Just the commit history changes with a new commit object.

Do not: amend the commits that are already pushed and present in a remote shared repository.

Another way:

Say you forgot to add/modify/delete a file before making the last commit.

git checkout branch2
echo “author:Name”>>README
touch database.log
git add --all

git status

On branch branch2
Your branch is up to date with 'origin/branch2'.

Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

        modified:   README
        new file:   database.log

Latest commit on ‘branch2’ before amending

* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch2, origin/master, origin/branch2, origin/branch1, master) [divya]

git commit --amend

v4: Add sub-functions, modified README, added database.log

[branch2 c0ebb4f] v4: Add sub-functions, modified README, added database.log
Date: Sat Aug 18 16:45:19 2018 +0530
3 files changed, 8 insertions(+)
create mode 100644 database.log

* c0ebb4f 2018-08-18 | v4: Add sub-functions, modified README, added database.log (HEAD -> branch2) [divya]

Commit id changed from ‘5fa64c6’ to ‘c0ebb4f’.

b) Reset the commits in the local repository: git reset –-soft

This command will reset the HEAD pointer to the commit id mentioned by the command.

Will not modify the files either in the Index or Working directory.

Project: reset_project

git checkout branch3
git hist

* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch3, origin/master, origin/branch3, origin/branch2, origin/branch1, master, branch2) [divya]
* 9429703 2018-08-18 | v3: main function added [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

git reset --soft HEAD~1

Local history changed after the ‘reset’, You could modify the project and recommit.

* 9429703 2018-08-18 | v3: main function added (HEAD -> branch3) [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

The file that was committed in the latest commit has been put back in Index; waiting to be committed.

NOTE: The ‘Staging area’ has not been affected as the file has not been un-staged.

git hist
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

        modified:   main.func

How will this help?
You could delete the bad commit; could modify/add/delete the project code and re-commit.

Summary: ‘git reset --soft' resets the local history allowing you to re-write the project history.

‘Index’ and ‘Working dir’ not affected.

Try also:

You can also reset the local history to any previous commit id.

git checkout branch4
git hist

* 5fa64c6 2018-08-18 | v4: sub-functions added (HEAD -> branch4, origin/master, origin/branch4, origin/branch3, origin/branch2, origin/branch1, master, branch3, branch2) [divya]
* 9429703 2018-08-18 | v3: main function added [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

History is reset to the first initial commit.

* 7558269 2018-08-18 | v1: Initial file added (HEAD -> branch4) [divya]

Latest project snapshot upto the commit id:‘7558269’ have been un-committed.

$git status
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

new file:   README
modified:   main.func

c) Reset to sync Working dir, Staging area and Local repository: git reset –-hard

git reset --hard commit-id
git reset --hard HEAD~1
git reset --hard HEAD~3

Permanent undo – lose your work

Used to:

a. Remove committed snapshots
b.Undo changes in staging area and working directory

Use it:

  • only to undo local changes

Do not use:

  • To reset snapshots that have been shared with others

The 3 states of the project and the effect of reset Diagram: The 3 states of the project and the effect of reset 

Its history is same as the previous branches and ‘master’

Make a new commit and check history

$echo "database log file.">db.log
$git add . && git commit -m 'Add db.log'

$git hist

* 9eb255a 2018-12-03 | Add db.log (HEAD -> branch5) [divya]
* 5fa64c6 2018-08-18 | v4: sub-functions added (origin/master, origin/branch5, origin/branch4, origin/branch3, origin/branch2, origin/branch1, master, branch4, branch3, branch2) [divya]
* 9429703 2018-08-18 | v3: main function added [divya]
* 4dcbe20 2018-08-18 | v2: README file added [divya]
* 7558269 2018-08-18 | v1: Initial file added [divya]

Undo the last commit that you made by mistake; reset to 1 previous commit pointed by HEAD

git reset --hard HEAD~1
HEAD is now at 5fa64c6 v4: sub-functions added

NOTE:

‘db.log’ file would be gone and the history will be reset back to commit id: ‘5fa64c6’

To reset to earlier named commit ids, you could also run as below:

git reset --hard HEAD~3
OR
git reset --hard 4dcbe20

13. Revert a committed snapshot or revert an old file: git

  • git revert is used to record some new commits to reverse the effect of some earlier commits/snapshot of a project.
  • Instead of removing the commit from the project history, it figures out how to undo the changes introduced by the commit & appends a new commit with the resulting content in the current branch.

Revert a committed snapshot or revert an old file

Usage: git revert <commit_id>

Use: To undo an entire commit from your project history; removing a bug introduced by a commit.

Reset Vs Revert

  • git “reset”: resets the project to a previous snapshot erasing the changes.
  • git “revert” does not change the project history unlike git “reset”
  • Git “revert” undoes the commit id changes and applies the undo work as a new commit id object.

Reset Vs Revert

Undo 1: Revert the recent commit

Projectrevert_Example

Latest commit history

$git hist
* b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (HEAD -> master, origin/master, test) [greets]
* 657c0d8 2015-07-29 | 3rd commit: file3 added, readme added [greets]
* fbd89be 2015-07-29 | 2nd commit: file1 deleted, file2 added [greets]
* f9deb74 2015-07-29 | 1st commit: file1 added [greets]

’Working dir’ before a revert

file2.txt file4.txt flie3.txt library.lib readme.txt

git revert HEAD
#edit the message in the editor if needed.

[master 81880fa] Revert "4th commit: added file4, library.lib and modified readme."
3 files changed, 2 deletions(-)
delete mode 100644 file4.txt
delete mode 100644 library.lib

#History remains the same, new commit id added with reverted changes

$git hist
* 81880fa 2018-12-03 | Revert "4th commit: added file4, library.lib and modified readme." (HEAD -> master) [divya bhushan]
* b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (origin/master, test) [greets]
* 657c0d8 2015-07-29 | 3rd commit: file3 added, readme added [greets]
* fbd89be 2015-07-29 | 2nd commit: file1 deleted, file2 added [greets]
* f9deb74 2015-07-29 | 1st commit: file1 added [greets]

Working dir after revert

$git ls
file2.txt flie3.txt readme.txt

Undo 2: Revert an old commit

Consider the same master branch with the latest revert commit we just made.

Let’s revert the ‘fbd89be’ commit changes

’Working dir’ before a revert

ls
file2.txt flie3.txt readme.txt

Check what was committed in this commitId

git show fbd89be

commit fbd89be6833556c57575fe4838eab0af15b56ee4
Author: greets <greetybhatnagar@gmail.com>
Date:   Wed Jul 29 11:29:29 2015 +0530
   
          2nd commit: file1 deleted, file2 added

diff --git a/file1.txt b/file2.txt
similarity index 100%
rename from file1.txt
rename to file2.txt

‘file1.txt’ was renamed to ‘file2.txt’. Let’s revert this change.

git revert fbd89be
[master 009612f] Revert "2nd commit: file1 deleted, file2 added"
1 file changed, 0 insertions(+), 0 deletions(-)
rename file2.txt => file1.txt (100%)

’Working dir’ after revert

file1.txt flie3.txt readme.txt

The reverted commit still remains in the history and a new reverted commit object is added.

* 009612f 2018-12-03 | Revert "2nd commit: file1 deleted, file2 added" (HEAD -> master) [divya bhushan]
* 81880fa 2018-12-03 | Revert "4th commit: added file4, library.lib and modified readme." [divya bhushan]
* b64f219 2015-11-26 | 4th commit: added file4, library.lib and modified readme. (origin/master, test) [greets]
……

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments

Ezeelogin

Thanks for the post. I liked the way all the details have been provided!

stephen

Firstly thanks for providing this tutorial from this article I have gathered lots of information. I can say that whatever the information provided by knowledgeHut is more useful to know more about the git.

Saurabh

Written nicely