Git (Advanced)
A) Branching Strategies:-
Consider you want to take the data from the website and put the same data into the database using Python script. Then my manager said that you can put your code in git. I will merge and review it.
Here the real scenario us that there are 3 branches named as Master, Staging and Dev. In Dev branch, developer develops the code. They will create branch (let’s called Feat1) and merge into Dev. From Dev branch, the code passes to Staging Branch. In Staging branch, people like Beta users, Stakeholders, QA will test and put it into master branch (called as Current Release / Protected Branch).
Now I' will discuss another branching strategy. There are 3 branches named as Prod, Stg, Dev. As usual in Dev branch, codes are being developed by developer. Here, the working is being tested by CI/CD pipeline. Then it passes to Stg branch where QA people will test it out. If there is any error, it will goes to Dev and developer will make changes in the code. If there is no error at Stg branch, then it goes to Prod. All the deployment strategies will being done on Prod branch. If there is any error in Prod branch, a new branch is created called ‘Hotfix’. This branch will solves your error instantly. Once it resolves the error, then it goes to Prod and Stg branch. QA people will test it and from there developer will pull the code from Stg branch.
B)Revert: It is known as Undo
Consider there are 2 commits (C1, C2) in master branch. From 2nd commit, you had create a new branch called Dev. You have created (C3, C4 (considered as incorrect commit), C5). Now you want to revert C4. If you revert C4, then it creates a new commit C6 on Dev. Whatever file you revert, it will not shown on your git directory but it will be shown on commit history.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch
master ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout -b dev
Switched to a new branch 'dev'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch feat2.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat2.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat:added feat2"
[dev de7c089] feat:added feat2 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat2.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch feat3.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat3.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat:added feat3"
[dev fe4b4a5] feat:added feat3 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat3.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch gadbad.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add gadbad.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat: added gadbad"
[dev baf52b5] feat: added gadbad 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gadbad.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat: added feat4"
[dev 555bc18] feat: added feat4 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
555bc18 (HEAD -> dev) feat: added feat4
baf52b5 feat: added gadbad
fe4b4a5 feat:added feat3
de7c089 feat:added
feat2 d81c429 (master) feat added feat1
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt gadbad.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git revert baf52b5
[dev fbb8366] Revert "feat: added gadbad" 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gadbad.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
fbb8366 (HEAD -> dev) Revert "feat: added gadbad"
555bc18 feat: added feat4
baf52b5 feat: added gadbad
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 (master) feat added feat1
C)Reset:- Now I want to reset the gadbad file. But don’t perform this operation. You need to reset fe4b4a5 commit ID so that it will delete the commit from gadbad commit. But the file will be shown on ls command. This type of reset is known as soft commit which means that the file won’t remove from work directory but it will remove from commit history. Hard Reset means that the file will be removed from commit history as well as work directory.
Note:- Perform Revert & Reset on Dev branch only.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch
*dev
master
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git reset fe4b4a5
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
fe4b4a5 (HEAD -> dev) feat:added feat3
de7c089 feat:added
feat2 d81c429 (master) feat added feat1
D)Merge:- Consider there are 2 branches. Master has C1, C2 and C3. From C3, I have created a branch called Dev having C4, C5, C6. When you do git status on C3, it will show as Nothing to commit. Head is pointing on C3. If you do git status on C6, it will show as Your branch is 3 commit ahead of master.
Now we want Dev branch into master branch. Here the master branch is known as Base branch. First go to base branch. Then run git merge Dev which creates a new commit on Master branch pointing from C3 to C7.
Note:- C7 is created from C6 (during merging). It is a normal merge called Fast Forward. If you don’t want a new commit, then you need to use No Fast Forward concept. C7 will be a new Head which points to Master, Dev.
Head points to the latest commit which maintains the previous commit history.
In Merge, we won’t see the timings of the commit and it’s history. Ge, Only C1, C2, C3, C7 will be carry out on Master.
Here in Dev bracnh, I have feat2.txt, feat3.txt and feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
fe4b4a5 (HEAD -> dev) feat:added feat3
de7c089 feat:added feat2
d81c429 (master) feat added feat1
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git status
On branch dev Untracked files: (use "git add ..." to include in what will be committed) feat4.txt
nothing added to commit but untracked files present (use "git add" to track)
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch
dev
*master
In Master, I have added feat1.txt and feat4.txt is now Untracked.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat4.txt
Now I want feat2.txt and feat3.txt on Master branch.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git merge dev
Updating d81c429..fe4b4a5
Fast-forward
feat2.txt | 0
feat3.txt | 0
2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat2.txt create mode 100644 feat3.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
fe4b4a5 (HEAD -> master, dev)
feat:added feat3
de7c089 feat:added
feat2 d81c429 feat added feat1
E)Rebase:- If we want C4, C5 on Master then we can use Rebase. I want to maintain linear history on Master. Here timing and commit history needs to be maintain in sequential manner.
Note:- Rebase will do merge and create a new commit but the branch will show the commits in linear manner.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git switch dev
Switched to branch 'dev'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat: added feat4"
[dev 8822ff5] feat: added feat4
1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master Switched to branch 'master'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch feat5.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat5.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat:added feat5.txt"
[master 1220c47] feat:added feat5.txt
1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat5.txt
Where is feat4.txt file. It is present in Dev branch.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
1220c47 (HEAD -> master) feat:added feat5.txt
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git merge dev
Merge made by the 'ort' strategy.
feat4.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
ac2568f (HEAD -> master) Merge branch 'dev' 1220c47
feat:added feat5.txt
8822ff5 (dev) feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
HEAD doesn’t points on Master and Dev. Last time it was pointing to both. This is not necessary merge will point on both the branches.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout dev
Switched to branch 'dev'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
8822ff5 (HEAD -> dev) feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
Rebase will be done on dev, because I want master branch to sync here.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git rebase master
Successfully rebased and updated refs/heads/dev.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
ac2568f (HEAD -> dev, master) Merge branch 'dev'
1220c47 feat:added feat5.txt
8822ff5 feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
Same commit history will be shown on master
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master
Switched to branch 'master'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
ac2568f (HEAD -> master, dev) Merge branch 'dev' 1220c47
feat:added feat5.txt
8822ff5 feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
F)How we can merge Pull Request on GitHub (PR)?
I want to push DevopsBatch directory on github
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch dev
*master
dev
Where I need to push, where is origin
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git remote -v
Create a new repository on Github with same name ‘DevopsBatch’
I am linking Github on my local
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git remote add origin https://github.com/bilal05041996/DevopsBatch.git
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git remote -v
origin https://github.com/bilal05041996/DevopsBatch.git (fetch)
origin https://github.com/bilal05041996/DevopsBatch.git (push)
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git push origin master Username for 'https://github.com': ^C
Create a token on github.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git remote set-url origin https://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@github.com/bilal05041996/DevopsBatch.git
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git remote -v origin https://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@github.com/bilal05041996/DevopsBatch.git (fetch) origin https://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@github.com/bilal05041996/DevopsBatch.git (push)
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git push origin master
A new branch is created called master on Github.
Note:- If I run git push origin main, then master branch will merge into main branch.
Now merge dev branch on Github.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout dev
Switched to branch 'dev'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git push origin dev
You can protect any one of the branch in Github. Go to Repository settings, click on Branches (shown on left side) > Add branch protection rule. Mention the branch pattern name as master. Go to Protect matching branches > Require a pull request before merging. No one will make changes in master branch before PR approval because master branch is now act as a Protected branch.
Create a new file in Dev branch. Once you created a file, then you need to click on Pull Request. Go to Settings > Collaborator. Add people so that they will get invitation. When you open PR, it means that you have make changes and now you will add into your project. Once they accept your invite then you can add them as a reviewer. They will approve or only commit or they will request some changes. Once hey approves, then you click on Merge. Here if you are merging dev branch into master branch on local, similarly when we perform same same operation on github, it is called as Pull Request. You can merge in 3 ways:-
a)Merge Commit: It will create a new commit after merge.
b)Squash and Merge: Consider Dev has 50 commits, master has 50 commits. If you merge dev into master, then master will contain 100 commits. It squash all the commits into one latest commit and merge.
c)Rebase and Merge: it will rebase and merged it.
Consider there is a dev branch on Github. When you run git pull origin dev on local, you are synchronizing both the branches. If there are multiple branches on GitHub, if you want to sync all the branches then we can run git fetch on local.
Create a new branch on Github called Staging
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch
*dev
master
I am adding staging changes on dev branch in my local.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git pull origin staging
Master and dev branch of Github sync on local.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git fetch
We can track remote branch.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout staging
branch 'staging' set up to track 'origin/staging'.
Switched to a new branch 'staging'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git branch
dev
master
*staging
You can fetch all branches.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git fetch --all
G)Hotfix / Cherrypick:-
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master Switched to branch 'master'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt feat5.txt
Consider feat4.txt has a bug
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout -b hotfix
Switched to a new branch 'hotfix'
This was a bug → Add content in feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat4.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "feat: resolved bug"
[hotfix 765e223] feat: resolved bug 1 file changed, 1 insertion(+)
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ touch feat-not-needed.txt ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat-not-needed.txt ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "added unwanted feature"
[hotfix 739aea5] added unwanted feature 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 feat-not-needed.txt
If I merge hotfix branch into master branch, the hotfix will come as well as unwanted feature would also come.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
739aea5 (HEAD -> hotfix) added unwanted feature
765e223 feat: resolved bug
ac2568f (origin/staging, origin/master, staging, master, dev) Merge branch 'dev' 1220c47 feat:added feat5.txt
8822ff5 feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
I want 765e223 commit ID in master
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master
Switched to branch 'master'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git cherry-pick 765e223 [master d67219f] feat: resolved bug Date: Mon Oct 28 06:49:25 2024 +0000 1 file changed, 1 insertion(+)
unwanted feature doesn’t come into master
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ ls
feat1.txt feat2.txt feat3.txt feat4.txt feat5.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ cat feat4.txt
This was a bug
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git log --oneline
d67219f (HEAD -> master) feat: resolved bug
ac2568f (origin/staging, origin/master, staging, dev) Merge branch 'dev'
1220c47 feat:added feat5.txt
8822ff5 feat: added feat4
fe4b4a5 feat:added feat3
de7c089 feat:added feat2
d81c429 feat added feat1
H)Stashing:- It hides your current changes.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout dev
Switched to branch 'dev'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ vim feat6.txt
This is an ongoing feature → Content of feat6.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat6.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "added feat6"
Now I’m adding other content in feat6.txt
I added a few changes → Content
Whatever you have changes in feat6.txt will be removed.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master
error: Your local changes to the following files would be overwritten by checkout: feat6.txt
Please commit your changes or stash them before you switch branches.
Aborting
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git stash
Saved working directory and index state WIP on dev: d25e6b4 added feat6
Now you can switch to master
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git checkout master
Switched to branch 'master'
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git status
On branch dev nothing to commit,
working tree clean
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git stash pop
On branch dev
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: feat6.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (ad4a3615b8c87857358c5156a2641524cc3eaf93)
git diff: You can see what changes you have added
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git diff
diff --git a/feat6.txt b/feat6.txt
index 0f5efeb..49dae68 100644
--- a/feat6.txt
+++ b/feat6.txt
@@ -1 +1,2 @@ This is an ongoing feature
+I added a few changes.
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git add feat6.txt
ubuntu@ip-172-31-25-118:~/impprojects/DevopsBatch$ git commit -m "I have modified few changes"
I)Conflict Merge:- Conflict Merges can occur when multiple developers are working on the same project and making changes to the same files, or when a single developer is working on multiple branches and making conflicting changes to the same files. Git tries to automatically merge the changes, but if can’t determine which changes to keep, it will stop and make the file as confict.
Case 1: Single developer work on multiple branches
ubuntu@ip-172-31-25-118:~$ mkdir MergeConflict
ubuntu@ip-172-31-25-118:~$ cd MergeConflict/
ubuntu@ip-172-31-25-118:~/MergeConflict$ git init
ubuntu@ip-172-31-25-118:~/MergeConflict$ vi index.html
Content: <h1> This is a Website </h1>
ubuntu@ip-172-31-25-118:~/MergeConflict$ git add index.html
ubuntu@ip-172-31-25-118:~/MergeConflict$ git commit -m "index.html file is created"
ubuntu@ip-172-31-25-118:~/MergeConflict$ git checkout -b b1
Content: <h1> This is b1 branch </h1>
ubuntu@ip-172-31-25-118:~/MergeConflict$ git add index.html
ubuntu@ip-172-31-25-118:~/MergeConflict$ git commit -m "b1 branch heading"
ubuntu@ip-172-31-25-118:~/MergeConflict$ cat index.html
This is b1 branch
ubuntu@ip-172-31-25-118:~/MergeConflict$ git checkout master
ubuntu@ip-172-31-25-118:~/MergeConflict$ cat index.html
This is a webiste
Switch to master and create a new branch b2
ubuntu@ip-172-31-25-118:~/MergeConflict$ git checkout -b b2
Content: <h1> This is b2 branch </h1>
ubuntu@ip-172-31-25-118:~/MergeConflict$ git add index.html
ubuntu@ip-172-31-25-118:~/MergeConflict$ git commit -m "b2 branch heading"
I want the changes of b2 branch into b1 branch. It will get an error when we try to edit same file at same line.
ubuntu@ip-172-31-25-118:~/MergeConflict$ git merge b2
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
ubuntu@ip-172-31-25-118:~/MergeConflict$ cat index.html
<<<<<<< HEAD
This is b1 branch
=======
This is b2 branch
>>>>>>> b2
You can abort the merge conflict.
ubuntu@ip-172-31-25-118:~/MergeConflict$ git merge --abort
You need to resolve the conflicts manually.
Open index.html and remove b1 code.
ubuntu@ip-172-31-25-118:~/MergeConflict$ git add index.html
ubuntu@ip-172-31-25-118:~/MergeConflict$ git commit
[b1 b6ef6e9] Merge branch 'b2' into b1