Skip to main content

Lab 2: Shell Scripting & Git

Overview

In this lab, you will learn how to use a linux terminal, practice some git commands, and write regular expressions.

To receive credit for this lab, you MUST show your work to the TA during the lab, and push your completed work to the github repositories by the deadline. Please note that submissions will be due right before your respective lab sessions in the following week. For Example, If your lab is on this Friday 10 AM, the submission deadline will be next Friday 10 AM. There is a "NO LATE SUBMISSIONS" policy for labs.

info

Please DO NOT close or clear your terminals as you are working through the lab as you may need to export some commands and their outputs for your submission.

Learning Objectives

LO1. Get familiar with git branching, merge conflicts and resolutions.
L02. Learn about pull requests and the difference between `git pull` and a pull request.
L03. Hands on practice with frequently used Shell commands
L04. Learn enough about regular expressions to be able to create basic ones
LO5. Learn advanced but commonly used git commands

Part A

Complete Pre-Lab quiz on Canvas before your section's lab time.

You should have gotten some practice with shell commands and regular expressions.

Part B

Practicing Git commands and learning to deal with merge conflicts

Clone your GitHub repository

info
You need to accept the invite to the GitHub classroom assignment to get a repository.

Github Classroom Assignment
For the next two steps, make sure to edit the name of the repository after the copying the command into your terminal.
git clone git@github.com:CU-CSCI3308-Spring2025/lab-2-version-control-<YOUR_USER_NAME>.git

Navigate to the repository on your system.

cd lab-2-version-control-<YOUR_USER_NAME>
HEADS UP

You will be simulating both persons of a pair for this part of the lab.

I. Managing code as a team - Person1's perspective

When working in a team, conflicts usually happen when two working Git branches diverge and the files are not consistent when the two branches are going to merge together. In the next few steps we will be simulating a conflict and learn how to fix it before merging the branches successfully.

i. Making code changes

As Person1: Update the README.md with you name and Github profile.

Format :<Firstname> <Lastname> - <Github username>

img

Run the following commands inside your local git directory. Make sure you have made the appropriate edits to the README.md file.

git add .
git commit -m "updated README.md with team details"
git push

ii. Pushing changes

1. As Person1: Create a new branch, with a sensible name of your choice.

git checkout -b "<Person1_branch_name>"

2. As Person1: Make changes to the file - main.cpp

caution

We are updating the return value in main only for demonstration purposes.

Change the return value to "1" in main.cpp

img

3. As Person1: Stage your changes

The git add command will stage any files you choose to be staged to commit (update) in your local Git repository. The .(period) lets you select all of the files that have been added or modified since the last commit. Here, we are specifying a file name to ensure that we are staging only the main.cpp file for commit.

git add main.cpp

4. As Person1: Commit your changes

Running the git commit command will now update your local git repository with the changes you staged. The -m flag is required and should be followed with whatever message you wish to state for your commit. This is part of your documentation, so try to make commit messages informative! Ideally, your commit message should indicate what changes are being made in this commit.

git commit -m "Version - <Person1> : <return value>"

5. As Person1: Push the branch to the remote repository

The git push command will upload your changes from your local repository to your remote Git repository which is hosted on GitHub. origin is the name of your remote whereas <Person1> is the name of the branch created by you as Person1. --set-upstream flag is used to push this new branch and set it as the default remote branch.

git push --set-upstream origin <Person1_branch_name>

The next time you choose to push to this branch you do not need to use the --set-upstream flag. You could simply use git push origin <Person1_branch_name>.

SWITCH ROLES

You will now be Person 2 in this scenario. Switch to the main branch using the following command:

git checkout main

6. As Person2: Make some edits on the main branch

Person2 will be in main branch. Before you start making edits you should pull the latest changes in remote.

git pull

Go ahead and change the return value to "2" in main.cpp

img

7. As Person2: Stage your changes

git add main.cpp

8. As Person2: Commit your changes

git commit -m "Version - main : <return value>"

9. As Person2: Push the changes to the main branch

git push origin main

iii. Merging Main

SWITCH ROLES AGAIN

You will now switch to being Person 1. Since you are simulating both persons, you already have the updated main. When working with other developers, always remember to run git pull frequently to ensure that your main is updated with the remote repository.

1. As Person1: Switch back to your branch

The following command helps you to toggle between branches.

git checkout <Person1_branch_name>

2. As Person1: Merge

Merge main on to your branch. You will come across a conflict.

git merge main
caution

Do NOT resolve conflicts through the GUIs!!

Before we go ahead and resolve merge conflict, let's understand how to inspect changes with the help of an example.

Following is an example showing merge conflict in a 'main.cpp' file.

By using your favorite editor, for instance VS Code, you can easily view the merge conflict on the UI. In the above example 'main.cpp' file, lines (12-14) after <<<< HEAD represents the current changes that you have, while the lines (14-16) represents the incoming changes from the remote repository i.e., changes made by some other person on the same section of code. You can accept either of the changes to resolve the conflict.

When working on an actual project, it is necessary that you contact that author of the code that is conflicting with yours and come to an agreement about how to resolve the conflict. It could mean accepting either solutions or re-writing a solution that includes both pieces of code.

iv. Resolving Conflicts

Now, that you have an understanding of how to view merge conflict(s), let's go ahead and resolve it!

1. View conflicts

Using your favorite editor, edit the "main.cpp" file so that it reflects either of the two changes (i.e. keep return 1 or return 2). Then, stage, commit, and push the "main.cpp" file.

2. Push the final version

git add main.cpp
git commit -m "Merging changes with return value <selected value>"
git push
🎥Recording output

Copy and Paste the output from your terminal showing the git conflict and then the resolution. Name this file git_merge_conflict.txt.

v. Create a pull request

1. As Person1: Create a pull request

Go the repository using the GitHub UI. Click on the "Compare & Pull request" button.

2. As Person1: Write a Description

Write a brief description for the pull request. Then, assign yourself as the assignee and for this example, assign the reviewer as yourself. In the industry, the reviewer would be a dev lead, team lead etc. Create the pull request.

3. As Person2: Review a pull request

Go to the "Pull Requests" tab and choose the pull request you were assigned to review.

Click on "Review changes" and add a comment to your review. Select "Approve" and submit the review.

4. As Person1: Merge your branch

Finally, merge the changes by clicking "Merge pull request".

Select "Create a merge commit."

Confirm the merge action.

Your PR is now merged. Nice work!

🎥Recording output

A screenshot of GitHub on your browser showing the log of the git pull request. Name this file git_pull_request.png.

Writing a Shell Script

We will now write a shell script called git_helper.sh that will help you run all the necessary git commands for a given repository.

Read the notes on Shell Scripting before proceeding to complete this task.

In the script, include the following operations:

  1. Check the status of changes - git status

  2. Stage the changes - git add

    Hint: You may consider requesting a list of files you would like to stage for the commit. You could default to a `.` to stage all updated files.
  3. Commit the changes - git commit

    Hint: You should request an input of commit message.
  4. Pull changes from the remote repository - git pull

  5. Push the changes to the remote repository - git push

Note: You will run the script in your terminal (MacOs, Linux) or WSL (Windows).

To be able to execute this script, make sure to add the necessary permission to it.

chmod +x git_helper.sh

To Run/Execute the file

./git_helper.sh
tip

If written well, you can use this script for all future labs/projects to submit your work.

🎥Recording output

For this section you will submit the git_helper.sh file.

Part C

In this section, we will learn additional git commands to cover some workflows you are likely to encounter working on your projects. We provide a brief summary of different commands and links to related materials. For a more thorough and interactive introduction to git, we recommend the Git branching tutorial. You will be completing activities in this section to learn the usage of each of these commands.

Git Branching tutorial

tip

While the git tutorial is optional, it is highly recommended!

Git Commands

info

We'll use the lab repository for these activities.

git log - activity

The git log command is used to view the history of committed changes within a git repository. The git log command only works on the committed history. Git log offers a number of options to customize your log output through filtering, ordering and formatting options.

To Do: Make sure NOT to close the terminal when completing this activity.

  1. Run the command -
git log --graph
  1. Now let's see what it looks like for a specific file.
git log main.cpp

Question 1. When was the file main.cpp last modified?

🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_log.txt`. You will also include answer to the question, above, in this file.

git fetch - activity

Pulls all newly added branches from remote so we can have all the new branches on our local tracking as well!

To Do: Make sure NOT to close the terminal when completing this activity.

  1. Go to GitHub and locate the repository for this lab.

  2. Create a new branch feature-branch-fetch on the website. You can reference this link

  3. In your terminal, run the command -

git branch

Question 1. Do you see the branch feature-branch-fetch?

  1. Now, let's run the fetch command -
git fetch origin feature-branch-fetch

Question 2. Do you see the new branch locally now?

Question 3. What would happen if we run the command git fetch --all?

🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_fetch.txt`. You will also include answers to the questions, above, in this file.

git rebase - activity

Git rebase is used when there are changes in main that we want to reflect and bring our branch to the same state as main. Rebase helps us create new commits for every commit on the original branch. Rebasing is useful because we have less conflicts and a cleaner structure.

git rebase branch structure

Image Credit: Atlassian Rebase Tutorial

To Do: Make sure NOT to close the terminal when completing this activity.

  1. Create a new branch called feature-branch-rebase and switch into it.
git checkout -b feature-branch-rebase
  1. Switch back into main

  2. Create a new file file1.txt and commit it to create a version number.

  3. Switch into feature-branch-rebase.

  4. Run the following command:

git log --oneline --graph
  1. Next run a git rebase with main:
git rebase main
  1. Again, check the git log.
git log --oneline --graph
Questions
  1. What changed before and after the rebase?
  2. How is git rebase different from git merge in this context?
🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_rebase.txt`. You will also include answers to the questions, above, in this file.

git rm - activity

We've already seen how to add files to be committed and pushed to a remote repository. But what if we need to remove any files from our repository that we no longer require? In this case, we can use the git rm command.

The git rm command is used to delete files from the git index. This command can be used to remove files from both the staging index and the working directory, but not only from the working directory.

To Do: Make sure NOT to close the terminal when completing this activity.

  1. To simulate an unneccesary file, let's create a file remove.txt. Add and commit it to the repository.

  2. The above step would ensure that the file is tracked by the git version control. Assuming we do not want to track it anymore, let's remove it from tracking.

git rm remove.txt

To persist this change, you will have to run the git commit command.

Question 1. Does the file exist on your computer after running the git rm command?

  1. In some cases, we may want to retain some files locally but not want it tracked by git anymore. For that situation we will use -
git rm --cached <filename>

Again, we must run the git commit command to persist this change.

Question 2. When must you use git rm vs. manually deleting a file? Question 3. How can you undo restore an accidentally deleted, by the git rm command, file?

🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_rm.txt`. You will also include answers to the questions, above, in this file.

git stash - activity

While working in a project team, you might run into a situation where, for instance, you're writing your code for a feature Ain your branch, but you are suddenly called by your coworker to give a hand in pushing a bug fix for another feature "B". In this situation, you'd want to save your current code and resume it from where you've left off after completing the bug fix. This is where git stash comes into play. Stash means to store/save your current changes safely in one place (stash stack). git stash temporarily shelves (or stashes) changes you've made to your working copy so you can work on something else, and then come back and re-apply them later on. Once you've stashed your changes, you're free to switch branches, commit new changes, and come back later and resume your saved or stashed work with git stash pop. Popping takes your changes from the stash stack and reapplies them to your current working directory.

By default, git stash does not stash the following: Files that have been ignored New files in your working copy that are not staged yet

So, in cases where you need to stash untracked files as well, you will need to execute the git stash command with the --include-untracked or -u flag at the end of the command.

git stash --include-untracked
# OR: git stash -u

To Do: Make sure NOT to close the terminal when completing this activity.

  1. Make and save some changes to the readme.md file.

  2. To simulate the need for an urgent branch switch, let's say a bug fix, let's checkout into another branch.

git checkout -b bugfix-branch-stash

Question 1. Were you able to make the switch?

  1. Given that we have some uncommitted changes in main, we need to run -
git stash

We can view the stashed changes using -

git stash list
  1. Now, let's try to switch to the other branch again -
git checkout -b bugfix-branch-stash
  1. Assuming the bug has been fixed and the changes have been committed. We'll move back to the main branch.
git checkout main
  1. We should retrieve the changes that we had previously stashed so we can continue working on them.
git stash pop

Question 2. What is the difference between git stash apply versus git stash pop.

🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_stash.txt`. You will also include answers to the questions, above, in this file.

git revert - activity

Git revert is commonly known as a way to "undo" commits in Git. Consider git revert as a "get out of jail free card" whenever you make a mistake while working on a project with others. You use git revert to create new commits that undo the effects of previous commits. For doing this it creates a new commit for undoing the changes, keeping the previous log as it is.

Following is the link that will help you to understand git revert better:

To Do: Make sure NOT to close the terminal when completing this activity.

  1. Create a file revert-activity.txt. Add some sample text to it. Save and commit the changes. Repeat this a few times to create a commit history of at least 5 commits.

  2. Run -

git log --oneline
  1. Let's say that we would like to undo the changes of a commit -
git revert <revision number>
  1. To verify that the revert was completed -
git log --oneline
  1. Review the contents of the readme.md file to see if the changes from that commit were undone.

Question 1. Can you revert multiple commits? Question 2. What happens if there is conflict during a revert?

🎥Recording output
You will copy and paste the commands and outputs of all the steps in this activity into `git_revert.txt`. You will also include answers to the questions, above, in this file.

Submission Guidelines

Create a folder called submission, within the lab repository, and include all the files listed below in that folder.

Expected files:

git_merge_conflict.txt
git_pull_request.png
git_helper.sh
git_rebase.txt
git_fetch.txt
git_rm.txt
git_stash.txt
git_log.txt
git_revert.txt

Commit and upload your changes

1. Make sure you copy your files for submission into your local git directory for this lab, within a "submission" folder that you need to create.
2. Run the following commands at the root of your local git directory, i.e., outside of the "submission" folder.

git add .
git commit -m "add all screenshots and changes for lab 2"
git push
3. Submit a link to the GitHub repository on Canvas.

Once you have run the commands given above, please navigate to your GitHub remote repository (on the browser) and check if all the files have been updated/uploaded. Once that is done, please submit a link to your repository on Canvas.

You will be graded on the files that were present before the deadline. If the files are missing/not updated by the deadline, you could receive a grade as low as 0. This will not be replaced as any new pushes to the repository after the deadline will be considered as a late submission and we do not accept late submissions. Please do not submit a regrade request for this.

Regrade Requests

Please use this link to raise a regrade request if you think you didn't receive a correct grade.

Rubric

CriteriaDescriptionPoints
Part A: Lab QuizThere is no pre-lab quiz for Complete Lab Quiz on Canvas20
Part B: Git merge conflict and resolutionA text file with your git merge conflict and resolution10
Part B: Git pull requestA screenshot of GitHub showing the log of the git pull request.10
Part B: Shell script to run git commandsShell script - git_helper.sh that allows for automation of basic git operations10
Part C: Take home sectionHands - on activities to practice git commands30
In-class check-inYou showed your work to the TA or CM.20
100