Homework 4
Version control
This assignment focuses on introducing the git
version control system (VCS) by practicing a very frequently-followed workflow: cloning a repository, staging and committing changes, and merging a feature branch into your main
branch. While your work for some of the tasks will be submitted as in an sh
file to Gradescope just as before, the Gradescope autograder will also check your CSE GitLab repository history and verify the tasks were completed and pushed successfully.
git
is a very complex tool. We strongly recommend using only commands introduced in class.
Enrolled students will have received email inviting them to a private repository in CSE GitLab. If you can’t find the email, you should also be able to find the repository by logging into CSE GitLab. If you can’t find your repository after logging in, be sure to ask on the discussion board!
Download the homework files on attu
After logging into attu
, download the homework files.
git archive --remote=git@gitlab.cs.washington.edu:cse391/25wi/hw4.git --prefix=hw4/ HEAD | tar -x
Add your repository link
In homework4.sh
, complete the print_link
function so that it prints-out the https
URL to your private repository exactly as it appears in your web browser address bar without any trailing #
character. The URL should end with your NetID.
For this part only, be sure to keep the echo
command so that running print_link
will print out your private repository URL.
Our autograder will grade this homework by cloning your private repository. Keep the your private repository page open in your browser since we’ll be using it frequently throughout this assignment.
Task 1: Create, edit, and move files
Let’s setup your repository. All the problems in this task are autograded by examining your remote repository history. You don’t need to edit homework4.sh
for the entirety of this task.
Clone your repository and add a README.md
On attu
, follow the Command line instructions on your private repository page to Create a new repository. The first command will clone (download) the repository from CSE GitLab, and the second command will change directory into your new, local copy of the repository.
git clone git@gitlab.cs.washington.edu:cse391/25wi/students/YOUR_CSE_NETID.git
cd YOUR_CSE_NETID
The next sequence of commands will create a main
branch, write an empty text file called README.md
, stage the empty README.md
file, commit the staged changes to the local repository, and finally push the new commit to the remote repository.
git switch --create main
touch README.md
git add README.md
git commit -m "add README"
git push --set-upstream origin main
At this point, running ls -a
should list the README.md
file alongside a hidden .git
directory.
README.md
- This empty file was just created with the
touch
command. Most repositories have some sort ofREADME.md
file that explains how the repository works. The.md
extension stands for Markdown, a language for styling and structuring plain text. .git
- This hidden directory stores important information about your local copy of the repository.
git
commands likegit add
andgit commit
record their changes in specially-formatted files stored in the.git
directory. There is usually no reason to make any changes to files inside the.git
directory.
After pushing commits from your local repository to the remote repository, if you now refresh your browser tab with your remote repository, you should see the empty README.md
file and your commit titled add README
.
This question is graded by looking in your repository for a commit that creates a file called README.md
. No edits need to be made to homework4.sh
.
Add a new Java file to your repository
Now that we’ve setup our local repository, let’s use it to develop software!
Copy the Facts.java
file from your hw4
directory into your local repository. Facts.java
calculates the factorial of its command line argument: we can calculate 5! by compiling and running it with javac Facts.java && java Facts 5
.
Since this is a new file, if we now run git status
, the output will explain that it is an untracked file. Stage the new file using the git add
command to add only Facts.java
.
git add Facts.java
If you previously compiled Facts.java
and now have a Facts.class
, be sure to only add Facts.java
. Do not add or commit any compiled .class
files to your repository!
Now that Facts.java
has been staged, we can now commit the change. For this problem, be sure that your commit message is exactly "Added Facts.java"
.
git commit -m "Added Facts.java"
Finally, push the changes in your local repository to the remote repository on GitLab.
git push
On GitLab, if you refresh the files, you should see that Facts.java
is now there.
This question is graded by looking in your repository for a commit that adds the Facts.java
file with the exact commit message Added Facts.java
.md. No edits need to be made to homework4.sh
.
Edit a file in your repository
If you open Facts.java
in vim, you’ll notice that it contains no documentation. Adding documentation not only helps explain how to use the program, but it also signals a degree of professionalism about the software: particularly important in helping users make a decision about which implementation to use.
Edit the file Facts.java
by adding at least one Java comment to the file. The contents of the comment aren’t graded, but you must add at least one comment using either //
or /*
.
To double-check your work, use git status
and git diff
. You can also check if your Facts.java
file still works properly by verifying that javac Facts.java && java Facts 10
outputs 3628800
.
Stage your changes, commit them, and push the changes to your remote repository with any descriptive commit message.
This question is graded by looking in your repository for a commit that modifies Facts.java
by adding at least one line that contains //
or /*
, representing a Java comment. No edits need to be made to homework4.sh
.
Rename a file (and class) in your repository
Facts.java
is great for computing factorials, but not so great for generating fun facts.
In order to accomodate both goals, rename Facts.java
to Factorial.java
so that we can later write a Facts.java
program that generates fun facts. Be sure to rename the class declared inside the Java program to Factorial
rather than Facts
too: if you don’t, the code will no longer compile!
Stage your changes, commit them, and push the changes to your remote repository with any descriptive commit message.
This question is graded by looking in your repository for a commit that renames Facts.java
to Factorial.java
. No edits need to be made to homework4.sh
.
Task 2: Exploring git commands
In homework4.sh
, write your answer to the following questions using only git status
, git diff
, git log
, or git blame
. It’s not necessary to run any commands in your local repository; instead, write your answers within the corresponding functions in homework4.sh
. Read the man
page for each command and experiment with them (especially git blame
, which we did not cover in the prework).
- Which command provides more information about just the most recent commit? Read the
man
pages to identify the necessary flag. - Which command outputs the differences between the most recent commit and its grandparent (2 commits prior)? The most recent commit is
HEAD
; a commitk
commits before the most recent commit is denoted byHEAD~k
. - Which command tells you who most recently changed each line of
Factorial.java
(and when)? Don’t usegit log
.
Task 3: Make and resolve a merge conflict
In real-world collaborative software development, we’ll often create a new branch, make some code changes, resolve a merge conflict, and then merge the new branch back into the main
branch. Specifically, we’ll focus on refactoring code, or reorganizing the program to improve code quality without affecting its behavior.
Switch to a new branch and refactor the code
First, we will create a new branch to make our change. From the main
branch, create a new branch called refactor-factorial
.
git switch -c refactor-factorial
In the main
method, remove the existing factorial calculation code:
- int fact = 1;
- for (int i = 1; i <= num; i++) {
- fact *= i;
- }
-
- System.out.println(fact);
Then, copy the following factorial
method and paste it inside the Factorial
class.
public static int factorial(int num) {
int fact = 1;
for (int i = 1; i <= num; i++) {
fact *= i;
}
return fact;
}
Finally, call the factorial
function at the end of the main
method.
System.out.println(factorial(num));
Before you add and commit your changes, check that your refactored code still works as intended.
java Factorial 0
should print out1
java Factorial 1
should print out1
java Factorial 5
should print out120
java Factorial 10
should print out3628800
Be sure not to commit the Factorial.class
file!
After committing your changes, push your branch to GitLab:
git push --set-upstream origin refactor-factorial
This question is graded by looking in your repository for a refactor-factorial
branch for a refactored Factorial.java
program that still works as intended. No edits need to be made to homework4.sh
.
Fixing an integer overflow bug
Since we’ve finished refactoring the code, it’s time to switch back to the main
branch so that we can keep up to date with everyone’s changes.
git switch main
Factorial.java
should no longer contain your refactored code. But we might realize that our Factorial
program gives the wrong answer for some larger numbers, such as java Factorial 20
, which outputs the negative number -2102132736
due to integer overflow. To fix this issue, change the type of the fact
variable to long
.
- int fact = 1;
+ long fact = 1;
Recompile the program and check that java Factorial 20
now outputs 2432902008176640000
. Stage your changes, commit them, and push the changes to your remote repository with any descriptive commit message.
Be sure not to commit the Factorial.class
file!
Merge the refactor back to main
Now that we’ve addressed the bug in the main
branch, it’s time to merge the refactor-factorial
branch back to the main
branch. From the main
branch:
git merge refactor-factorial
git
should report a merge conflict! To fix this conflict, edit the Factorial.java
file so that the resulting code merges the ideas from both branches:
- The resulting code addresses the integer overflow problem at least on
java Factorial 20
. - The resulting code refactors the math logic into its own method called
factorial
. Remember to update the method signature to return along
rather than anint
! - The resulting code compiles and runs properly on all previous examples.
java Factorial 0
should print out1
java Factorial 1
should print out1
java Factorial 5
should print out120
java Factorial 10
should print out3628800
java Factorial 20
should print out2432902008176640000
Stage your changes, commit them, and push the changes to your remote repository. For this commit, we suggest keeping the default commit message; simply save and exit the editor. Then, push your changes to remote.
This question is graded by looking in your repository for a merge commit in main
as well as the final main
branch providing the correct output for java Factorial
on 0
, 1
, 5
, 10
, and 20
. No edits need to be made to homework4.sh
.