Navigating the Cosmic Git: A Majestic Journey through Git Exercises
Tags: git, beginners, tutorial, opensource
Published: 2024-05-07 21:03:39

## what is this all about?
This is blog I wrote after attempting to complete Git exercise by fracz. So, speaking about git exercise it's a set of tasks that will give you a basic understanding of how Git works and various commands that you can try out. You can try out by going to [Git Exercise] (https://gitexercises.fracz.com/), go here and follow the steps mentioned. So going further I am hoping you all know about what [Git](https://git-scm.com/docs/gittutorial) is and why it has great importance in this industry. Buckle up let's go for the adventure of understanding git.
> Note: we are using **Terminal** and **VS code**(you can go with whatever you are comfortable with) to do the tasks so hope you have basic understanding of both.
- Make sure you have Git installed on you local machine if don't, you can get it [here](https://git-scm.com/downloads). 

> **Make sure you go to next task by executing `git start next` after you finish one challenge.**


1. **Push a commit you have made**
       ```
       - git start
       - git verify
       ```
       > Note: usually you need to use `git push` to push your changes to the source control but for tutorial purposes we are going to keep using `git verify`.

2. **Commit one file**

       When you proceed to this stage, two new files are created. We are instructed to commit one of these files using the git add command, which adds the file to the staging area where you can commit.
       ```
       - git add A.txt
       - git verify
       ```
       > Note: git only commits the files or changes you have made only if you staged them using `git add <file name>`.
       - Additional Info: 
           - You can add all files to the staging area by using `git add .` or `git add -A`.
           - You can stage all changes made to the file in the commit command itself using the -a flag in the commit command. `git commit -am <"Commit message">`. Note that it does not stage new files that have not been previously added to the repository with `git add`.

3. **Commit one file of two currently staged**
    
    We are instructed to commit just one of the two files that are presently staged for commit in this job. For this, we can use the `git reset <file name>` command. One file will be helped to unstage.


    ```
    - git reset B.txt
    - git commit -m "<Commit message>"
    - git verify
    ```
    > Note: `git reset` is like your Ctrl+Z in Git. It lets you undo changes, unstage files, or move your project's current state to a specific point in time

4. **Ignore unwanted files**

    This task asks that we exclude certain files that finish in specific extensions. We can use the [`.gitignore`](https://git-scm.com/docs/gitignore) file for this purpose. By instructing git to ignore specific files based on their name or specific rules, it helps us maintain a clean source control system.


    ```
    # create a .gitignore file (for Linux users -> touch .gitignore)
    - vim .gitignore #I am using vim here you can use VS code or any other means necessary.

    - # write the following into the file :


    *.exe       # *.exe will select every file with .exe extension
    *.o         # *.o will select every file with .o extension
    *.jar       # *.jar will select every file with .jar extension
    libraries/  # this will make git ignore the whole library directory   

    

    - git add .gitignore
    - git commit -m <"Commit message"> 
    - git verify
    ```

5.  **Chase branch that escaped**

    This task instructs us to include a [git branch](https://git-scm.com/docs/git-branch) to our next commit. We can do that by using [`git merge`](https://git-scm.com/docs/git-merge) `<branch name >`

    ```
    - git merge escaped
    - git verify
    ```

6.  **Resolve a merge conflict**
    
    In this we need to merge a branch named `another-piece-of-work` to our current branch but if we try to merge we will get a [merge conflict](https://www.geeksforgeeks.org/merge-conflicts-and-how-to-handle-them/), we need to solve the issue causing this.

    
    ```
    - git checkout merge-conflict
    - git merge another-piece-of-work

    # There will be conflict when you do this to-fix you can either open it up in VS code and use merge analyzer to figure out and fix it. i will be using vim
    - vim equation.txt #it's the file causing the issue


    # will remove everything from the file and then write:
    2 + 3 = 5

    - git add equation.txt
    - git commit -m "merge and resolve"
    - git verify
    ```

    > Note: Merge conflict occurs in Git when two branches have competing changes to the same part of a file, making it impossible for Git to automatically resolve the differences. It requires manual intervention to decide which changes to keep, typically by editing the conflicting file to incorporate the desired changes.

7.  **Saving your work**
    
    This requires us to save our work somewhere, find the bug as soon as possible, correct it, and then return to our work, finish it, and commit. Using git, we can accomplish this by using [`git stash`] (https://git-scm.com/docs/git-stash), which will store your work in a stashing area. From there, you can work on your projects as you choose, commit them, and return to your work by popping the stash.


    ```
    - git stash                              # pushing the current work to stash
    - vim bug.txt                            #fix the bug in the file 
    - git commit -am "<Commit message>"      # committing after fixing the bug
    - git stash pop                          #poping the leftover work that we push to stack earlier
    - vim bug.txt                            #write "Finally, finished it!" to the end of the file 
    - git commit -am "<Commit message>"      #commiting after finishing our part of work
    - git verify 
    ```
    
8.  **Change branch history**
    
    What we are supposed to do is to make the branch tree look like 

    ![image containing the branch tree we need](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1x69abtnays0x6mehco.png)
    That is put the branch you fixed the bug before the branch you are working on.

    > We can use [`git rebase`](https://git-scm.com/docs/git-rebase) to change the current branch tree to the one we want.

    ```
    - git rebase hot-bugfix
    - git verify
    ```
    
9.  **Remove ignored file**
    
    This is a pretty common issue if you committed something and decide to not have that in your codebase later to achieve that you can [`git rm`](https://git-scm.com/docs/git-rm). 
    > Note: this won't remove the file from the local machine but will remove the file from the other people when they do a next [`git pull`](https://git-scm.com/docs/git-pull).

    ```
    - git rm ignored.txt               #if you wanted to delete a whole directory give -r flag meaning recessively removing.
    - git commit -am "<Commit message>"
    - git verify
    ```


10.  **Change a letter case in the filename of an already tracked file**
   We must rename a file that has previously been tracked in this. There are a few different ways to tackle this one, but I'll choose to rename the file and commit the modifications. The command `mv` (for Unix systems) or `move` (for Windows) can be utilized. 


    > Note: Despite the tool's name being move, you can rename a file by passing in the file name as the first argument and the desired new name as the second.


    ```
    - mv File.txt file.txt
    - git rm File.txt
    - git add file.txt
    - git commit -m "<Commit message>"
    - git verify
    ```
 
    
11.  **Fix typographic mistake in the last commit**

    This is a typical error, and we don't want other people to be aware of our insignificant dump blunders, do we? Thus, we must modify the contents of the most recent commit while keeping it a secret from others. To do this, we can use [`git commit --amend`] (https://stackoverflow.com/questions/26050327/). We can change the most recent commit by executing this.


    ```
    - # Fix the typo in the file
    - git commit -a --amend      # -a to add the changes made in the file 
    - # in the opened page edit the commit message
    - git verify
    ```
    
12.  **Forge the commit's date**
    This requires us to change date of the previous commit you can use [--date] (https://stackoverflow.com/questions/19742345/what-is-the-format-for-date-parameter-of-git-commit) flag with --amend which will change the date of the last commit.

    ```
    - git commit --amend --no-edit --date="1987-08-03"    # --no-edit for having no edit in the commit message.
    - git verify
    ```
    > Note: --amend only lets you edit just before commit.
    
13.  **Fix typographic mistake in old commit**
    
    To fix a typo in an old commit, start an [interactive rebase](https://git-scm.com/docs/git-rebase) `git rebase -i HEAD^^`. Change "pick" to "edit" for the commit with the typo. Correct the mistake in file.txt, add it `git add file.txt`, then continue the rebase with `git rebase --continue`

    ```
    - git rebase -i HEAD^^
    - change "pick" to "edit" where the typo is in the commit message
    - #fix the typo in the file
    - git add file.txt
    - git rebase --continue
    - #fix the rebase conflict
    - git add file.txt
    - git rebase --continue
    - git verify
    ```
    
14.  **Find a commit that has been lost**

    For this task we need to retrieve the commit that has been lost due to `git commit --amend`. For this we can use [`git reflog`] (https://git-scm.com/docs/git-reflog) after which we can just reset to that commit to get back to the required file.

    ```
    - git reflog
    - git reset --hard HEAD@{1}
    - git verify
    ```
    
15.  **Split the last commit**
       For this task, we are to split the commit into two parts. The best command to use is git reset, which will reverse the previous commit including the two files, and then we can commit each file individually.

    

    ```
    - git reset HEAD^
    - git add first.txt
    - git commit -m "<Commit message>"
    - git add second.txt
    - git commit -m "<Commit message>"
    - git verify
    ```
    
16.  **Too many commits**
    
    Our task is to squash the last two commits into a single commit while preserving the changes made in both commits. This will consolidate the changes and keep the project history clean. For this we can use the [interactive mode rebase](https://git-scm.com/docs/git-rebase) and edit the commits we want to combine.

    ```
    - git rebase -i HEAD~4
      # replace "pick" with "squash" for the commit with the message "Crap, I have forgotten to add this line." 
      # Give a commit message for the commit which is the result of combining two commits
    - git verify
    ```
    
17.  **Make the file executable by default**
    
    Our task is to modify the Git history to add the executable bit for script.sh, enabling users on Unix systems to execute it without needing to manually set permissions. For that we can add the file to git with specific permissions beforehand and then store that int he staging area, we can use [--chmod](https://stackoverflow.com/questions/40978921/how-to-add-chmod-permissions-to-file-in-git) with git add hence specifying the permission needed to git.

    ```
    - git add --chmod=+x script.sh
    - git commit -m "<Commit message>"
    - git verify
    ```
    
18.  **Commit part of work**
    
    We are required to commit the changes we have made thus far twice from a single file for this task; to do this, we may divide the modifications and commit for each one using the `-p` (part) flag while staging the file.


    ```
    - git add -p file.txt
      # This will prompt you to select specific changes to stage. You can choose which parts of the changes to include in the first commit.

    - git commit -m "<First commit message>"
      # Commit the first set of changes.

      # Repeat the process for the second set:
    - git add -p file.txt
      # Select and stage the remaining changes.

    - git commit -m "<Second commit message>"
      # Commit the second set of changes.
    - git verify
    ```


    > Note: Additionally, you may stash, reset, or checkout certain file sections. To these commands, just add the -p parameter.

19.  **Pick your features**
    
    We are asked to rebase each feature branch onto the pick-your-features branch to consolidate their changes into a single commit on pick-your-features. For this we can use [`git cherry-pick`](https://git-scm.com/docs/git-cherry-pick), it selects a specific commit and applies its changes onto the current branch. we can use that to pick individual feature commits onto the `pick-your-features` branch.

    ```
    - git cherry-pick feature-a                 # Selects and applies the changes from the commit related to 'feature-a' onto the current branch.
    - git cherry-pick feature-b                 # Selects and applies the changes from the commit related to 'feature-b' onto the current branch.
    - git cherry-pick feature-c                 # Selects and applies the changes from the commit related to 'feature-c' onto the current branch.
  # resolve merge conflict                   
    - git add .                                  # Adds all changes, including those from the cherry-picked commits, to the staging area.
    - git cherry-pick --continue                # Continues the cherry-pick process after resolving conflicts, if any.
    - git verify                                
    ```
    
    > Note: When cherry-picking, remember to resolve any merge conflicts that may arise before continuing with `git cherry-pick --continue`.

20.  **Rebase complex**
    
    We are asked to rebase the commits H and I from the "rebase-complex" branch onto commit D in the "your-master" branch using a single Git command. For this, you can use `git rebase` with the `--onto` flag followed by the target branch `your-master`, the source branch `issue-555`, and the last commit to include `rebase-complex`.
    ```
    - git rebase --onto your-master issue-555 rebase-complex 
      # By doing this, the rebase-complex branch is rebased. It reapplies the fixes to the your-master branch that were added after the rebase-complex branch diverged from the issue-555 branch. This effectively gives the impression that the rebase-complex branch was built straight off of the your-master branch.
    - git verify
    ```
    
21.  **Change order of commits**

    For this, we are instructed to switch the order of the last two commits in the Git history, as indicated by running the command git log -2. You can easily do that with you previous experience in [git rebase] (https://git-scm.com/docs/git-rebase).

    ```
    - git rebase -i HEAD~3
    # reorder the commit messages
    - git verify
    ```
    
22.  **Find commits that introduced swearwords**

    For this, we are instructed to locate all commits that add the word "shit" to either `words.txt` or `list.txt` and replace them with the word "flower" instead, ensuring that the history reflects this change without removing the previous instances. we can do that with search attribute of [`git log`] (https://git-scm.com/docs/git-log) and [`git rebase`] (https://git-scm.com/docs/git-rebase).

    ```
    - git log -S shit                      # -S flag help to search for "shit" in commit 
      # Note the commits where the word "shit" was introduced.
    - git rebase -i HEAD~100
      # Initiates an interactive rebase for the last 100 commits, allowing for modification of commit history.

      # Checks which files were modified in the latest commit.
    - git log -p -1
      # Search for the word "shit" and replaces it with "flower" in list.txt.
    - git add list.txt
    - git commit --amend
    - git rebase --continue

      # Checks which files were modified in the latest commit.
    - git log -p -1
      # Search for the word "shit" and replaces it with "flower" in words.txt.
    - git add words.txt
    - git commit --amend
    - git rebase --continue

      # Checks which files were modified in the latest commit.
    - git log -p -1
      # Search for the word "shit" and replaces it with "flower" in words.txt.
    - git add words.txt
    - git commit --amend
    - git rebase --continue

    - git verify
    ```
    
23.  **Find commit that has introduced bug**
    
    For this, we are instructed to locate the first commit that introduces the word "jackass" into the application's main screen text, which is encoded in base64 in the source code. We must find this commit, verify it, and push it for further examination. This requires creating a unit test to automate the search process, decoding the text, and utilizing Git commands such as [`git log`] (https://git-scm.com/docs/git-log), [`git bisect`] (https://opensource.com/article/22/11/git-bisect), and [`git grep`] (https://git-scm.com/docs/git-grep) to navigate through the project's history effectively. We are told that 1.0 is a good commit so we can take that as the good reference for git bisect.
    

    > Note: You can make an automation python script called [git python] (https://gitpython.readthedocs.io/en/stable/tutorial.html) to do this task if you wish I will be talking about git bisect.

    ```
    - git bisect start HEAD 1.0
    - git bisect run sh -c "openssl enc -base64 -A -d < home-screen-text.txt | grep -v jackass" 
    # This will do a bisect search to find the 1st commit with "jackass" included you need to note this as `COMMIT ID`.

    - git push origin <`COMMIT ID`>:find-bug
    - git verify
    ```