Download as pdf
Download as pdf
You are on page 1of 40
SPAHUVSS AMS HF*SVLS|NS A hA#SVL ASA he? Git Merge & Rebase FB vost SAHKVSSMHA*SVLAS ASML L_S)}N SARS? Git Merge & Rebase Both git merge and rebase, kind of perform the similar task of covabining/joining the development histories together. Now, what does that mean? Sivaple, in git we have concept of branches, we usually have a default (master or main) branch, and then as part of our regular development/fix work we create feature/velease branches out of it. Once we are done making our changes in our feature branches we want it to be published to remote branches and also combined with the main or master branch to keep it unified and accessible to others with their changes. Hence, we need some feature ta jain these changes/histary from different branches, Both Merge & Rebase let you do that. The end goal is to combine the changes but how it is done is what waakes Merge & Rebase different. Let's understand thera with a simple example - oS featuve/one ct - ¢2 - c4 - cS master You basically created a feature branch ‘feature/one! from master when they were both at covamit 'c2' and then you added a new commit ‘e3' to the feature and also added 2 new commits 'c4' and '¢5" to master branch, So, at the moment feature is unaware of the commits c4 & cS which are on the master and also the master branch has no clue of covamit c3 which is on feature. ideally that's fine as both are different branches, but if there is a need to combine them into one destination, then it is needed to know about all these commits. SAHUVASASMHA*HLAS AM hA*bsL ASA hH? Git Merge & Rebase Now, suppose We Want to combine the changes from the master branch to feature/one branch. **Use the image in last slide as starting point for each of the below operation. 1. Let's perform Merge - git checkout feature/one git merge master cS — cé feature/one 7 4 e1 - ¢2 - C4 - CS waster You are at your feature branch and performed ‘git merge master’ to merge the changes of master branch into your feature branch, So, in order to merge the changes a néw merge Commit 'cé! got created which binds histories Frova both the branches on feature branch, So if you now do a ‘git log! you will see a chronological order of commits For e.g -> CL - c2 - 63 - c4 - e& - c& (assuming ¢ commit was done prior to c+ wrt time) 2. Let's perform Rebase - git checkout feature/one git rebase waster master e1 - €2 - c4 - cS - c3*feature/one Rebase, as its name suggests, it actually resets the base. So earlier 'c2' was Common between feature and waster branch, we can call it the base. Now, when we fire rebase commana, it will actually pick all commits in feature after ‘¢2' which is just 'e3' commit. First it will apply all commits frou master into the featuré and on top it it applies the 'c3' commit. Why ¢c3* é& not cB? Will explain it. Git Merge with example - Partt - We are on the master branch, and it has 2 commits. Now, let's create a feature branch ‘feature/test_merge' from master branch and switch to it. The commits ave same as master branch. new commits to the feature branch and 1 new commit to the master] g/git/merge_and_rebase (feature/test_merge Let's draw an image which depicts the commits at the moment to understand it better - (badfd7) - (75/0920) feature/test_merge (a7efieb) - (61621997) - (4f4930a) master - It's time to do the Merge. We are on the master branch and we merged feature into master. Git Merge with example - Part2 As we merged the feature branch into the master. Master should now contain all the changes from feature. Btw, when you ran the merge command a text editor was opened for you to give the merge commit message. Nac Sea ee (badfd7 9) - (75f071¢) feature/test_merge 4 (a7cfieb) - (61614947) - (4f4930a) - (Sad43fe) master So, this is how the merge operation is performed. You can clearly notice one important thing here, that in the histery every commit hash is consistent. In other words no change in the history took place, but the only change is addition of a new merge commit (Sad43fe in the above scenario) fam sure you can imagine the simpl in the overall operation while performing the merge. Looks like just a game of pointers. Git Rebase with example - Partt Let's see how Rebase works and how it is different from Merge. Again, our objective is same. We will create a feature out of master. We will be adding new changes/commits to both feature and master, And then we will doa rébase this time to Combine changes from feature to the master branch. Both ‘master’ and ‘feature/test_vebase' ave in-syne at the moment. Now, let's add 2 new commits in the feature branch and + new covamit in the master branch. (bfazede) - (6722162) feature/test_rebase “ (722fsfe) - (aeedeb?) - (ece72d9) master Git Rebase with example - Part2 - It's time de perform Rebase. What exactly happened here? 4. The base has been reset, from the last base to a new base Earlier it was (aeadeb@) and now has been reset to (6722262) 2. The new commits from master (which were not in feature) are applied on top Messagé 2 in this case. feature /testvebase (S4623fe) master (722fSf2) - (aeedebq) - (bfa2ede) - (¢7222b2) - Koeezada) Rebase operation is performed on the master branch. You can clearly see what happened. Firstly all the commits of the ‘feature/test_rebase' are applied on the last common commit between master and feature (aeedeba). And then on top of it the new commit from master is applied (Message 3). But wait, the commit hash looks different. Earlier it was ece72d9 and now it is Sdeasfe. Why? SAHSVASAS AM HhM*SL SSA bFHL_ SSA HH? To Summarize - It looks like both Rebase and Merge did there job well. And yes that's true. In both the cases we got the feature branch changes combined into master branch. But, one thing which is still not clear, why the commit hash changed in case of Rebase operation. Yes, that's how Rebase is done. When you did the merge, no change was done wrt history (no commit hash changed), just a new merge commit was added. But in case of Rebase, it actually rewrites the commit history. So, it is not basically a lift and shift of pointers but also rewiting a new commit of same changes. We first get the new base and then on top of it we write again the changes as new commits. And that's what makes Rebase a little risky and complicated operation if not performed carefully as it is rewriting the history. It is always suggested to avoid doing Rebase in a branch/repo being used publicly or shared with other developers as it could create a mess. Use Merge in such scenarios. You can use Rebase when your changes are on your feature and don't affect others. Like performing squash of commits ete. SAHSVASAS AM HhM*SL SSA bFHL_ SSA HH? Git pull vs Git pull --rebase git pull or git pull --merge Performs : git fetch + git merge This is the default case. In this case, your local changes ave merged with the remote changes. A new merge commit is created pointing to the latest local commit and the latest remote commit. git pull --rebase Performs : git fetch + git rebase In this case, your local changes are reapplied on top of the remote changes. So, the new changes on your local ave picked, first the remote changes are applied which gives a new base and then your changes that were picked are applied on top as new commits. Bonus command :P git checkout - To switch to the last branch you were at. This command can be used to switeh to and fro between the branches. Resolving Conflicts To generate a merge conflict - We created a text file ‘conflict.txt! on both master and feature branch. Added 2 different ines in file on each branch. Now we ave trying to merge master changes into the feature branch. The moment we did ‘git merge master on feature, it gave us merge failed evvor and is expecting us to resolve the conflicts manually We checked the content of conflict.txt file. The content between "<<<<666e<¢ HEAD" & "= is from our current =" & "3292222 master" is from the branch which we ave merging which is branch which is feature here. And the stuff between "= master here. Suppose we want to keep the change from feature branch, hence we will remove what's coming from the master and add this file again Soi eS r t stot ena teas iste 0 eo ee Ree! git merge --continue To continue the merge operation. git merge --abort To abort the merge process. It will try to reconstruct the pre-merge state Thanks!!! ee ee ee Git Stash stash ~ to store safely in a hidden or secret place. @mayank ahuja ae Let's understand with an actual scenario - You are currently inside the local repository ‘git-demot’ which is in-sync with the remote repository and you don't have any local changes. aac) Ret a ales There is a text file ‘test.txt” which we will be using for the demo. Printed the content of the file. @mayank ahuja ae Now, let's add new lines in the text file. Added 2 new lines. ara en eee a y eS my fifth Tine @mayank ahuja ae Now due to some reason you don’t want these new changes in the text file now, but you want to keep them stored somewhere locally as you might need them later. You basically need a clean working directory at the moment. git stash’ can help you in this scenario. The command saves your local modifications away and reverts the working directory to match the HEAD commit. SCs Panes “git status’ shows that the test.txt file has been modified. But as we wanted to stash the changes we ran ‘git stash save "message" command and did ‘git stash list’ to check the stash and we can see that our change has been saved. @mayank ahuja ae Now if you do ‘git statu: are gone. as ent SO eo oreo at Soceeeimare ro ead But what if you need the stashed changes back? You need those 2 lines back in the text file. ‘git stash pop’ command gives you the last stashed change. arate Soe as) rd reais ) aia EL ana ee emer tier That's mainly how stashing works. Now let's learn some more commands wrt git stash. @mayank ahuja ae ‘$e ‘git stash list” - to know all stashed changes that are available/stored ‘git stash save" is now deprecated and hence you can use ‘git stash push’ instead to stash a change git stash push -m “message” aoe a aa onan ea mena @mayank ahuja ae ‘<$~ ‘git stash pop’ vs ‘git stash apply" You can use either of them to re-apply the stashed change to the working directory, but the difference is, pop will remove the change from stash (stack) but when you do apply it's kept intact in the stack, git stash pop coe Sos ear creer) ePvats} @mayank ahuja ae “> git stash apply ra PCs Pei er errr cise) eC ar ‘9/git/git-demol (m You can clearly see that even though the change was re-applied the entry is still present in the stash. @mayank ahuja ae > git stash apply ad Pec eet EC Ree) pre Clears the stashed items. ot) List shows no entries. @mayank ahuja COC git reset / revert Let's UNDO Current state - The local repository is in-syne with the remote, we have 2 text files (demoOne & demoTwo) that already exsists on remote and our working directory is clean(no local changes at the moment). Let us learn, (master) er Se Cle ree a cee eae Date: Tue Apr 26 21:39:58 2022 +0530 Ce Coan eee Coreen eee eats eC es esas herr eerer) adding few Tines to demoOne file rset ace SUL ee berate eet CCRC ea a learn, Oro) cars Ce eens Sa Oro) eee eats aie en Rt ae eR acc t us learn Oro) Cad VOC Rn aera) forts] eect lon branch master rc Ue een MC yee nothing to commit, working tree clean Let's add a new line in each file and ereate a new commit for each change. eres (master) ee eee Coots eo (coe) re Let us learn, coe) ee OC eC eC eC) 1 file changed, 1 insertion(+) are fore) Pe i a ee Cr acd oy cca) rae oa (coe) Case C CT Aunt Le (master) S$ git log een ener eens nee Pare pate: Tue Apr 26 2 eRrorietrrn This is how th pee ere meee is is haw the commits look like eee eee eee ren een eae now CC tat eee Set cee cce) Ce Ree aary Pec ornite i added in our local CUCM ae eee Re Cus eared elas DC eed ees Pree repo. adding demoTwo file We are actually eee eee ea now 2 conuuits elas a ees fh re Ee) ahead of the coe remote. ee eee Penta elas Perret Es EC ot aa mayank S git reset --soft Let om (2th eee ele eee er Cee i) eae rep) caer) POR eee eer aa ceec te L eare tea Tue Apr 26 21:39:58 2022 +0530 ee ea Se Cree eR ec ae Tue Apr 26 21:39:09 2022 +0530 CC a ea eee Ree eee Tue Apr 26 21:38:20 2022 +0530 Cr Cut aa Let us learn, cer) Peer Pu Nour branch is up to date with ‘origin/master’. GO Coe (use "git restore —-staged reset to 2 commit after current HEAD, HEAD~2 -> 2 commits after HEAD ete.) When you perform reset, it always undo all commits after specitied commit and not just that commit or a specific range. mayank_at a) git reset --mixed ee ee ee ieee oad In Cees Im Cees ey crap) est lon branch master ree ee ar re ae eee ese ect sd Cr ae as oe a Mn) (use "git restore ..." to discard changes in working directory) ae cre] rae) Author: mydemo222 Conn seer re oraneLe Sean Mee reer Cee ce fo Ce ed seer Relea) Ce Re un Me eee Cee ese Ce ee oREL Eee eee) Eee aa What actually happened? When you pass the flag ‘mixed! (which is default), it behaves similar to ‘soft! in the sense that the changes are not lost from the local but are unstaged. So, you need to add thera again if you need them back before doing commit or may be stash them. Here we moved 1 commit ahead from prev HEAD. Or in other words removed all commits after HEAD-1 . > git reset --hard As in the last change we did soft reset, let's add back the unstaged files and also commit them. Added a new commit '8b2¢a... HEAD pointer updated [Crt s ia) ws Tear Crp] ECU Se ec Tue Apr 26 22:14:30 2022 +0530 Ce er eee aoe eae Sete Esme eerie tet) Se Now, when we use Deets eed in Tue Apr 26 21:39:09 2022 +0530 the flag ‘hard’ in Roe Cee ee eae the reset command, It vesets the Sere eee ener ee ea ence ee commit but also elas SCT es eee bear Lt) removes all Cm Cent aE changes from rer (master) local which where Feehan eee eC Coc naa part of those eae a) coop) commit(s). eat eee Working directory Your branch is up to date with ‘origin/master’. . is clean, Inathing to commit, working tree clean mw nk_ahu ja a og git revert This is the current state, we are in syne with the remote repo. Seer Coe) git revert command sounds similar to reset, and yes both are like performing the undo operation, but reset was much cleaner that revert. Why so? When you perfrom the vevert operation, it will undo the commit (or range of commits) but it also adds extra commits te perform this revert. So, basically git history would have the commit that had the change plus a commit which was used to revert the change. Let's see that in the next slide, what happened when we fired the revert, = > hen we fired the revert command in prev slide, it actually asked to add a commit message for the revert we are going to perform. With revert Sera en we can actually Eee eta ter undo any specific Please enter the commit message for your changes. Lines starting commit or range eC UU me ae . . 2 . of commits. With reset it was resetting Om Pee ee are is Se 3 ad everything after the specified commit. We can't specify a range there. (master) ar Pe irre ec Reece eeece Date: Tue Apr 26 22:15:33 2022 +0530 A new revert a commit has been added. This is a Revert command demo ~ Reverting “adding demoTwo file This reverts commit ca54bc9c0486922e6683eaf8442d1 eSdea8Safb9. ee ree eer Rone Cae Tue Apr 26 21:39:58 2022 +0530 Se a Now, doa i ‘git push' ee ree aera Rene eee gt P ree eee eee) if you Want ee a this change to appear on the : mydemo222 Part 1 Assume the local branch is in-sync with the remote branch at the moment. Both ‘master’ (local copy) and ‘origin/master’ (pointer to remote master) ave pointing to the same commit ‘s4ad... Now, suppose one of your teammate has added/pushed a new file on master remote branch. You local master is not aware of that change. Let's do ‘git fetch’ and see what happens. git fetch [CeCe Oh! t can only see ‘master’ pointing to 'séad..", but where is ‘origin/master' ? in/master got updated to what's in the remote When you did ‘git fetch’ the ovi master. As your teammate added a new change, it must be pointing to it. git pull is git fetch + git merge -> Part 2 ~ Let's find out where is ‘origin/master' _git log origin/master er crest] IS git log origin/master Ce ee eee eee SUE Laser CRs eee) rcs Pe ee eee eer St ec LTe reese) eae eas See, the ovigin/master points to the latest commit which is on remote master, but your local master still points te ‘sad. old covamit. How can we syne them again? git merge we need to doa merge no a forerio) ec Veta CLEC MET eet) aera ger Pieces ad CReL ute Ea aT TGD) eC Awesome, both origin/master and master are now pointing to the same cormit. ee) ced ee eee ese CeCe Be Ser tertile dec ET) es pe eee ae ee STE Beene Ee eae) resend git pull is git fetch + git merge -> Part 3 We can perform the complete ‘git fetch' + ‘get merge’ thing by just doing ‘git pull’. Assume, that your teammate again added a new text file on remote master and you local master is unaware of the change. Current state - ‘git log! arr (master) ea) ce PO eee eee een ener a me pris Thu Apr 28 21 5 2022 +0530 ccs eee eee een (re Cees S Eee cae) aera = Let's do ‘git pull' and see what happens : git pull When we did ‘git pull', et us Tea (master) an aie a ie it first performed Sa ee eee ee ‘git . ed eons ate CL eRe agit fetch’ followed by Cet aa RCD CL ‘git merge’ Total 3 (delta 0), reused 0 (delta 0), p Tiegh el Sian ee ee enn ae urea reed Cert ee ee Tenet ae as p pointir eo raaster’ pointing to Panel samme new commit. ‘origin/master’ & Cee eee Thu Apr 28 21:42:50 2022 +0530 CS ea Creating and Publishing a Local branch to Remote ~ create a local branch ‘feature/demot' and switch te newly ereated branch. git branch featuve/demo1 git checkout -b feature/demor OR git checkout feature/demot ee er Cor koe ais c ona ean GESEL fear) rte branch ‘fea ae (creas) t leg cated er eee een Cee es Dee ee Een eee Third commit cue See et Steeler aes s Sec LE) Second commit ee reseed pr ae eee Perse rZ ae SEs) aeons - viewing last n commits (in this case 2 commits) git log -n2 ian (master) $ git log -n2 cies Oe reece ae (re ee Cea err BE MeL aeSC Es) SR eee ee ee eos Thu Apr 28 20:42:42 2022 +0530 oer mets — one liner info of every commit git log --oneline ey core) er ae ved Third commit Second commit eas (creas) rey cated er eee een Cee es tee ee Third commit See et Ree CECE ar ese s Sec E Second commit eed Sec tar, prea ee ere Pere cae) aeons - skipping last n commits (in this case 2 cormmits) git log --skip=2 et u fcretaD] IS git log --ski Sees, eee a (te ee ee Be reese ec) oats — grep commits by string/pattern git log --grep="Second" ae (creas ea ee ee ese Thu Apr 28 20:42:42 2022 +0530 cures git cherry-pick is cool As the name sounds, it is used to pick changes from existing commit and apply them by creating a new commit. Let's see a simple example. We are on ‘feature/demo' branch currently and we have added a new change with commit id '32.904..'- Created hello file Se at We can see the ‘master’ is behind by 1 commit from the feature. We know one way to updated ‘master’ is by doing merge with the feature branch. But here, we will see how cherry-pick works. We can pick a commit and apply. So let's pick the commit '32.904..' and apply it to master. Let's switch to master and do cherry pick. After cherry -pick the same changes from that commit crc 1 file changed, 1 insertion(+) are applied to re ae ee master branch. s git To = / ? ee But it created a new commit with a different oe Can shat. Let's see the difference - difference between 2 commits git diff commit commit2 al... from commits ‘s4ad...' & b/... is from commit2 ‘a7eLO..". You can see 2 files (hello.txt and pull.txt) were added in commit2. ~ similarly you can see diff of tip between two branches git diff bvanchA branchB - to see difference between your local (unstaged) vs staged(indexed) changes git diff to see difference between staged(indexed) changes vs what's commited your local wepo git diff --staged oR git diff --cached ens eee) In a nutshell Stash Working Staging Local Remote as| Tree, Area, Repo Repo git stash git diff t git diff staged + f git diff --cached! git pop : o> > git apply : git ade + git commit git push git rm : git fetch + git merge git rebase git pull " & mrayank_ahuja

You might also like