1. 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.