24sp ver.

Note: this is for the Spring 2024 iteration of CSE 391. Looking for a different quarter? Please visit https://courses.cs.washington.edu/courses/cse391/.

  1. Let’s practice the pull request workflow!

    • Go to https://gitlab.cs.washington.edu/ and create a new project by selecting “New Project”. Select “Create an empty project”. Give it any name you’d like (e.g. 391-lecture-5) and put it in your user group/namespace (should be an option in the drop down).

    • Clone your repo to your machine. Select the Code dropdown on your repo’s home page and copy the “Clone with SSH” link. Then run git clone <clone-with-ssh-link>. You’ll need to be on a machine that has your ssh key setup (e.g. whatever machine you used for HW4).

    • On main, create a new file todo.txt. Add, commit, and push your changes to main. Note that this is not the pull request workflow! We get to that in just a second.

    $ touch todo.txt
    $ git add todo.txt
    $ git commit -m "Adding empty todo.txt file"
    $ git push
    
    • Starting on main, create two new branches. You could imagine two new developers branching off of main at a similar time (though they’d do it on their own machines).
    git checkout main
    git checkout -b add-fun-todo
    git checkout -b add-school-todo
    
    • On the add-school-todo branch, add a TODO related to school to todo.txt. Add, commit, and push your changes to add-school-todo.

    • Navigate to your repository in the GitLab UI. Create a merge request for the add-school-todo branch targeting main. You can do this a number of ways - one option is to navigate in the UI to Code -> Merge Requests and create a merge request there. Source (where you are merging from) should be add-school-todo and target (where you are merging to) should be main. You can leave the other options untouched.

    • Feel free to look at the components of the merge request. In particular, notice the “Changes” tab that allows you to see the changes you made. Pause and think about what kind of things you might look for if you were reviewing someone’s changes in a coding project. When you are done looking around, merge your pull request by clicking “merge”.

    Solution

    There are no rules for reviewing code - each team you work with will have their own preferences. Some things you could comment on:

    • Code design/architecture decisions and refactorings
    • Code readability
    • Code correctness (e.g. edge cases to consider)
    • Any other questions or thoughts you have while reading the code!
    • In your cloned repo, switch to the add-fun-todo branch (e.g. git checkout add-fun-todo). Add a TODO related to something fun to todo.txt. Note that your school TODO is not in this version of the file - this is because add-fun-todo is based off a previous version of main. Add, commit, and push your changes to add-fun-todo.

    • Repeat the steps to create a merge request for add-fun-todo. You should see a notice indicating “Merge blocked”. This is because your add-fun-todo branch has changes that conflict with the changes on main. Pause and think about when/why this might happen when working in a repository with other people.

    Solution

    Often times when developing code, you will create a branch off main, and while you are working on your branch, a fellow developer merges new changes into main. The other developer’s changes might touch the same files as your changes, resulting in merge conflicts.

    • Resolve the merge conflict. Here we will show you how to do it locally, but you could also resolve them in the UI if you’d like in the future. In your cloned repo, perform the following steps - it would be good to pause and think about why each step is necessary:

      • Switch to the add-fun-todo branch if you aren’t already on it

        git checkout add-fun-todo
        

      • Retrieve the latest version of the remote repository

        git fetch
        

      • Merge the latest version of main from the remote into your add-fun-todo branch

        git merge origin/main
        

      • Fix any merge conflicts. Then commit and push to the add-fun-todo branch.

      • Navigate back to the merge request in the GitLab UI. You should now be able to merge your changes!

  2. In your own words, why might it be bad practice to push directly to the main branch of a repository? What might be a better practice instead? What are some ways that projects enforce these practices?

Solutions

One of the biggest reasons to avoid pushing to main directly is main should always be a publishable state of your project. You never want to include a commit that might cause a sort of bug or has unintended changes added.

Additionally, we usually want the commit history of a project to tell a good “story” about the development of the project (e.g., “Add Feature X”, “Fix Bug 1234”, etc.) instead of a bunch of commits trying to fix merges into main. Since everyone on a team eventually makes changes to the main branch, it helps keeps things simpler if people operate via merge requests instead of pushing directly.

Many projects explicitly forbid merging into main directly. Websites like GitHub and GitLab have features that owners of a repository can enable to prevent developers from pushing to main directly.

  1. What are the commands to create a new branch, switch to that branch, and commit a set of staged changes? Are there any shorthands for these commands?
Solutions

Below is the general workflow

# Create a new branch called feature
git branch feature

# Check out that branch
git checkout feature

# Make some changes to files
...

# Stage and commit
git stage file1 file2 file3
git commit -m "Commit message"

There is a shortcut for making a new branch and immediately checking it out

git checkout -b feature
  1. Suppose that we have two branches branch1 and branch2 and git log tells us that HEAD is pointing to branch2. What are the command[s] to merge branch2 into branch1?
Solutions

To merge, you need to check out the target branch (the branch you want to merge into) and then issue the merge command to specify the source branch (the branch with the changes you want to merge in). Since this problem specified we are currently on branch2, we first need to switch to branch1.

git checkout branch1
git merge branch2
  1. Suppose we’re working on branch2, and we’ve opened a merge request to merge into main on GitLab. Someone else makes changes to main which causes conflicts with our changes. How might we resolve these changes on Gitlab and then preview them locally?
Solutions

The GitLab UI will show you that your merge request can’t be merged because there are conflicts.

One way to resolve this is with the GitLab UI using the “Resolve Conflicts” button.

Another way is to use your local version of the branch to make new changes from main into your branch locally, and then push those new changes.

A more advanced solution can locally use the git rebase command to re-play all the changes in your branch as if they were applied after the newest version of main was created. This is a fairly complex operation though, and we don’t recommend using it until you are more comfortable with git.

  1. Suppose that we knew our project was in a working state when we made a commit with the message: Commit 1. How might we temporarily put our local repository in the same state as it was when we made that commit? How might we identify what changes we’ve made since then?
Solutions

Just like you can checkout a particular branch, you can also checkout a particular commit. When you type git log, it shows a “commit hash” next to each commit that uniquely identifies the commit.

When you checkout a particular commit, you will likely end up in a “Detached HEAD” state. This means HEAD (which is the current commit you are referencing) is not currently on a named branch.

If you want to compare this commit to another, one way is to say git diff HEAD main which will compare the current HEAD to the main branch.

  1. What does git diff do?
Solutions

The git diffcommand shows the code changes between two commits or between the current repository and an earlier commit. This command executes a diff function against a Git data source. We can view the lines that have been removed from our original file, as well as any lines that have been added or modified.