#90DaysOfDevOps - Day 10: Advance Git & GitHub for DevOps Engineers.

Introduction

Today is the 10th day of the 90DaysDevOps challenge, where we're diving into advanced Git & GitHub for DevOps Engineers. We'll be exploring things like git branching (which is like making different paths for our work), git revert and reset (fixing mistakes), git rebase (kind of like rearranging our work), and git merge (mixing different parts of our work together).

Then, we'll get our hands busy with some practice. We'll make a new file, change it a lot, and save our changes multiple times. We'll also undo some of the changes we made. Plus, we'll add new paths for our work, make changes in one path, and bring those changes into the main path. We'll even try out git rebase to see what happens. Ready to start this adventure? Let's go!

Git branching

git branch1

Think of branches as separate lanes for developing. They're like asking for a new space to work on things, with its own area for changes and history. When you use branches for different features, you can work on them at the same time without messing up the main work. This keeps the main part clean from any uncertain changes.

Branches allow you to develop features, fix bugs, or safely experiment with new ideas in a contained area of your repository.

Some common commands

git branch List all the branches in the repository

git branch <branch> Creates a new branch called <branch> but does not checks out the new branch.

git branch -d <branch> Deletes a branch. If there are unmerged changes, Git does not allow you to delete it.

git branch -D <branch> Forces delete the branch, even if there are unmerged changes. Execute this command when you are sure to delete it permanently.

git branch -m <branch> Moves or renames the current branch to <branch>.

git branch -a Lists all the remote branches.

git revert and git reset

git revert: Git revert is used to create a new commit that undoes the changes made by a specific commit or a range of commits. It's a safe way to undo changes without rewriting history. The commit history will show the original commit followed by a new commit that reverses those changes. The original commit remains in history.

  1. Identify the commit you want to revert. You can find the commit hash using git log.

  2. Use the following command to create a new commit that undoes the changes:

     git revert <commit_hash>
    
  3. Git will open an editor for you to provide a commit message. Save and close the editor to create the revert commit.

git reset: Git reset is used to move the current branch pointer and the staging area to a specified commit. It can be used to "rewind" the history, but it's important to note that it should be used with caution, especially if the commits have been pushed to a remote repository.

There are different modes of git reset:

  • Soft reset (git reset --soft <commit_hash>): Moves the branch pointer to the specified commit without changing the staging area or working directory. The changes in the "reset" commits will appear as uncommitted changes.

  • Mixed reset (default) (git reset <commit_hash> or git reset --mixed <commit_hash>): Moves the branch pointer and updates the staging area to match the specified commit, but does not change the working directory. The changes from the "reset" commits will appear as uncommitted changes.

  • Hard reset (git reset --hard <commit_hash>): Moves the branch pointer, updates the staging area, and changes the working directory to match the specified commit. Be cautious with this mode as it discards all changes after the reset point.

  • git reset HEAD~n is a variation of the git reset command that allows you to move the branch pointer to a specified number of commits back in the history. The n in HEAD~n represents the number of commits you want to move back.

git merge and git rebase

git merge: It is the process of combining the changes from one branch into another. Here's how you would merge your changes from a feature branch (let's call it feature-branch) into the main branch (main or master).

  1. Check out the main branch:

     git checkout main
    
  2. Merge the feature-branch into the main:

     git merge feature-branch
    

    This will create a new commit on the main branch that represents the merge of the feature branch.

When you merge a branch into another, you create a new commit (merge commit) that has two parent commits: the last commit on the main branch and the last commit on the feature branch. This creates a clear indication in the commit history that a merge has taken place.

git rebase: It is a process that moves the entire history of one branch onto another, essentially replaying the changes from the source branch on top of the target branch.

  1. Checkout the feature branch**:**

     git checkout feature-branch
    
  2. Rebase the feature branch onto the main:

     git rebase main
    

    This will apply your changes from the feature branch on top of the latest changes on the main branch.

Rebasing rewrites the commit history of the feature branch. It creates new commits with new hashes, as the original commits are replayed on top of the target branch. This can result in a cleaner, linear commit history without merging commits.

Task 1

Add a text file called version01.txt inside the Devops/Git/ with “This is the first feature of our application” written inside. This should be in a branch coming from master, [hint try git checkout -b dev], switch to dev branch ( Make sure your commit message will reflect as "Added new feature"). [Hint use your knowledge of creating branches and Git commit command]

  • version01.txt should reflect at the local repo first followed by the Remote repo for review. [Hint use your knowledge of Git push and git pull commands here]

Add a new commit in dev branch after adding below mentioned content in Devops/Git/version01.txt: While writing the file make sure you write these lines

  • 1st line>> This is the bug fix in development branch

  • Commit this with the message “ Added feature2 in development branch”

  • 2nd line>> This is gadbad code

  • Commit this with the message “ Added feature3 in the development branch

  • 3rd line>> This feature will gadbad everything from now.

  • Commit with the message “ Added feature4 in the development branch

Restore the file to a previous version where the content should be “This is the bug fix in the development branch” [Hint use git revert or reset according to your knowledge]

Let's execute

We had already created "Devops" GitHub repo in the previous day's task. We will continue using the same.

Assuming you already have the "Devops" repo as a local repository.

#create a new and shift to the new branch "dev"
ubuntu@~/Devops$: git checkout -b dev
Switched to a new branch 'dev'

#create new file "git/version01.txt" and add content to the same file
ubuntu@~/Devops$: echo "This is the first feature of our application" > git/version01.txt
#view the content
ubuntu@~/Devops$: cat git/version01.txt 
This is the first feature of our application

#move the changes to staging area
ubuntu@~/Devops$: git add .
#commit the changes with suitable message
ubuntu@~/Devops$: git commit -m "Added new feature"
[dev df4abbb] Added new feature
 1 file changed, 1 insertion(+)
 create mode 100644 git/version01.txt

Now that we have committed the changes to "version01.txt" file, we will now push the changes to GitHub.

#push the changes of branch dev to GitHub
ubuntu@~/Devops$: git push origin dev
Enter passphrase for key '/home/ubuntu/.ssh/id_ed25519': 
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 398 bytes | 398.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
remote: 
remote: Create a pull request for 'dev' on GitHub by visiting:
remote:      https://github.com/pka2412/Devops/pull/new/dev
remote: 
To github.com:pka2412/Devops.git
 * [new branch]      dev -> dev

We will continue adding more changes to "version01.txt" file.

ubuntu@~/Devops$: git branch 
* dev
  main

#add new contents to the file
ubuntu@~/Devops$: echo "This is bug fix" >> git/version01.txt 
#view the contents
ubuntu@~/Devops$: cat git/version01.txt 
This is the first feature of our application
This is bug fix
#move the changes to staging area
ubuntu@~/Devops$: git add -A
#commit the changes
ubuntu@~/Devops$: git commit -m "Added feature 2"
[dev 597a10a] Added feature 2
 1 file changed, 1 insertion(+)

#add new contents to the file
ubuntu@~/Devops$: echo "This is gadbad code" >> git/version01.txt
#view the contents 
ubuntu@~/Devops$: cat git/version01.txt 
This is the first feature of our application
This is bug fix
This is gadbad code
#move the changes to staging area
ubuntu@~/Devops$: git add -A
#commit the changes
ubuntu@~/Devops$: git commit -m "Added feature 3"
[dev 0163f58] Added feature 3
 1 file changed, 1 insertion(+)

#add new contents to the file
ubuntu@~/Devops$: echo "This feature will gadbad everything now" >> git/version01.txt 
#view the contents 
ubuntu@~/Devops$: cat git/version01.txt 
This is the first feature of our application
This is bug fix
This is gadbad code
This feature will gadbad everything now
#move the changes to staging area
ubuntu@~/Devops$: git add -A
#commit the changes
ubuntu@~/Devops$: git commit -m "Added feature 4"
[dev d6c75a9] Added feature 4
 1 file changed, 1 insertion(+)

Restore the file to a previous version where the content should be “This is the bug fix in the development branch”. First we get the commit id of the commit.

#get the commit id from the log
ubuntu@~/Devops$: git log --oneline
d6c75a9 (HEAD -> dev) Added feature 4
0163f58 Added feature 3
597a10a Added feature 2
df4abbb (origin/dev) Added new feature
23ac50c (origin/main, origin/HEAD, main) Added day 2 file
0983dd8 Initial commit

#reset the branch to commit id "df4abbb" and also discard the changes using "--hard"
ubuntu@~/Devops$: git reset df4abbb --hard 
HEAD is now at df4abbb Added new feature
#view the content. We see only first line is present.
ubuntu@~/Devops$: cat git/version01.txt 
This is the first feature of our application
#view the log
ubuntu@~/Devops$: git log --oneline 
df4abbb (HEAD -> dev, origin/dev) Added new feature
23ac50c (origin/main, origin/HEAD, main) Added day 2 file
0983dd8 Initial commit

Task 2

  1. Add some changes to dev branch and merge that branch in main

    We will add around three changes to the "dev" branch.

     #create new git/version02.txt file with some content
     ubuntu@~/Devops$: echo "This is feature 2 implementation" > git/version02.txt
     ubuntu@~/Devops$: cat git/version02.txt 
     This is feature 2 implementation
     #stage and commit the changes
     ubuntu@~/Devops$: git add -A
     ubuntu@~/Devops$: git commit -m "Added feature 2"
     [dev d7a3075] Added feature 2
      1 file changed, 1 insertion(+)
      create mode 100644 git/version02.txt
    
     #next change
     ubuntu@~/Devops$: echo "This is feature 3 implementation" >> git/version02.txt 
     ubuntu@~/Devops$: cat git/version02.txt 
     This is feature 2 implementation
     This is feature 3 implementation
     #stage and commit the changes
     ubuntu@~/Devops$: git add -A
     ubuntu@~/Devops$: git commit -m "Added feature 3"
     [dev 2b1b7ce] Added feature 3
      1 file changed, 1 insertion(+)
    
     #next change
     ubuntu@~/Devops$: echo "Bug found in feature 2. Fixing the bug" >> git/version02.txt 
     ubuntu@~/Devops$: cat git/version02.txt 
     This is feature 2 implementation
     This is feature 3 implementation
     Bug found in feature 2. Fixing the bug
     #stage and commit the changes
     ubuntu@~/Devops$: git add -A
     ubuntu@~/Devops$: git commit -m "Fixed bug in feature 2"
     [dev 3d2230b] Fixed bug in feature 2
      1 file changed, 1 insertion(+)
    
     #view the log to see the commits
     ubuntu@~/Devops$: git log --oneline 
     3d2230b (HEAD -> dev) Fixed bug in feature 2
     2b1b7ce Added feature 3
     d7a3075 Added feature 2
     df4abbb (origin/dev) Added new feature
     23ac50c (origin/main, origin/HEAD, main) Added day 2 file
     0983dd8 Initial commit
    

    After adding changes to "dev" branch, we will merge them to the "main" branch and view the commit history.

     #switch to "main" branch"
     ubuntu@~/Devops$: git checkout main
     Switched to branch 'main'
     Your branch is up to date with 'origin/main'.
    
     #merge the changes from "dev" to "main" branch
     ubuntu@~/Devops$: git merge dev
     Updating 23ac50c..3d2230b
     Fast-forward
      git/version01.txt | 1 +
      git/version02.txt | 3 +++
      2 files changed, 4 insertions(+)
      create mode 100644 git/version01.txt
    
     #view the log to see the commits
     ubuntu@~/Devops$: git log --oneline 
     3d2230b (HEAD -> main, dev) Fixed bug in feature 2
     2b1b7ce Added feature 3
     d7a3075 Added feature 2
     df4abbb (origin/dev) Added new feature
     23ac50c (origin/main, origin/HEAD) Added day 2 file
     0983dd8 Initial commit
    

    After merging the "dev" to the "main" branch, we see that all the commits/changes that were made in the "dev" branch are now present in the "main" branch.

  2. As a practice try git rebase too, and see what difference you get

    Create a new branch "feature" and add two changes to the branch.

     #create a new and switch to the new branch "feature"
     ubuntu@~/Devops$: git checkout -b feature
     Switched to a new branch 'feature'
     #add first change
     ubuntu@~/Devops$: echo "This is new feature implementation" > git/feature.txt 
     ubuntu@~/Devops$: cat git/feature.txt 
     This is new feature implementation
    
     #stage and commit the change
     ubuntu@~/Devops$: git add -A
     ubuntu@~/Devops$: git commit -m "Added new feature"
     [feature 800d30f] Added new feature
      1 file changed, 1 insertion(+)
      create mode 100644 git/feature.txt
    
     #add next change
     ubuntu@~/Devops$: echo "Fix bug in the feature" > git/feature.txt 
     ubuntu@~/Devops$: cat git/feature.txt 
     Fix bug in the feature
    
     #stage and commit the change
     ubuntu@~/Devops$: git add -A
     ubuntu@~/Devops$: git commit -m "Fixed a bug in feature"
     [feature 92f0632] Added new feature
      1 file changed, 1 insertion(+)
      create mode 100644 git/feature.txt
    

    Now perform rebase "feature" to the "main" branch.

     #view the log before rebase
     ubuntu@~/Devops$: git log --graph --oneline 
     * 92f0632 (HEAD -> feature) Fixed a bug in feature
     * 800d30f Added new feature
     * 3d2230b (main, dev) Fixed bug in feature 2
     * 2b1b7ce Added feature 3
     * d7a3075 Added feature 2
     * df4abbb (origin/dev) Added new feature
     * 23ac50c (origin/main, origin/HEAD) Added day 2 file
     * 0983dd8 Initial commit
    
     #switch to main branch
     ubuntu@~/Devops$: git checkout main
     Switched to branch 'main'
     Your branch is ahead of 'origin/main' by 4 commits.
       (use "git push" to publish your local commits)
     #rebase feature to main branch
     ubuntu@~/Devops$: git rebase feature 
     Successfully rebased and updated refs/heads/main.
     ubuntu@~/Devops$: git log --all --decorate --oneline --graph
     * 92f0632 (HEAD -> main, feature) Fixed a bug in feature
     * 800d30f Added new feature
     * 3d2230b (dev) Fixed bug in feature 2
     * 2b1b7ce Added feature 3
     * d7a3075 Added feature 2
     * df4abbb (origin/dev) Added new feature
     * 23ac50c (origin/main, origin/HEAD) Added day 2 file
     * 0983dd8 Initial commit
    

Conclusion

To sum up, Git's branching, reverting, resetting, rebasing, and merging features are vital tools for organized and collaborative development. Branching lets you work on multiple tasks in isolation while reverting and resetting help fix mistakes and backtrack when needed. Merging and rebasing integrate changes, with merging creating clear merge points and rebasing offering a linear history.

Our hands-on exercises demonstrated the practical application of these concepts. Creating files, branching for features, and merging changes emphasized the value of Git's capabilities. In collaborative settings, these skills foster efficient teamwork and conflict-free development.

"🌱 Keep learning, and spread the knowledge to inspire others. 🚀💡"

Go back to the main page