Introduction to Git¶
Git is a system used for developing software in a group. In a nutshell, Git is a version control system that maintains files in a repository that contains not just files, but also a record of all the changes made to those files. Git tracks every version of a file or directory using commits. When you have made changes to one or more files, you can logically group those changes into a “commit” that gets added to your repository. You can think of commits as “checkpoints” in your work, representing the work you’ve done since the previous checkpoint. This mechanism makes it possible to look at and even revert to older versions of a file by going back to your code as it was when you “checkpointed” it with a commit.
You will each have a set of personal Git repositories, one per assignment, that will be hosted on a central server.
This lab provides a tutorial-style introduction to various aspects of Git. All you need to do is follow the instructions. Please do make sure you understand what is accomplished in each step and, if you have any questions, please don’t hesitate to ask for help.
Where should you do this lab?¶
For this lab, we will specifically need you to work on a CS machine, which means you will either have to work in CSIL or connect remotely to the CS environment. You can connect remotely in one of two ways:
Using SSH, which will allow you to open a command-line terminal on a CS machine. The CS techstaff provides detailed instructions on how to do this.
Connecting to a Virtual Desktop. This will show you, on your computer, effectively the exact same desktop you would see if you physically logged into a CSIL machine. However, this option may not work well for low-bandwidth Internet connections.
Throughout this lab, you will have to make some simple edits to a few text files. If you are using SSH, we suggest you use a command-line editor for editing (like Vi, emacs, nano, etc.), or Ubuntu’s built-in Text Editor if using the Virtual Desktop. You do not need to use a full-featured code editor in this lab.
Getting started¶
In the capp-camp-a21
Slack channel, we have supplied a few URLs that you
will need as you work through this lab. Please open a browser and log
into the CAPP Slack to have access to these links.
For each assignment, a Git repository will be created for you on GitHub, a web-based hosting service for Git repositories. However, before that repository can be created for you, you need to have a GitHub account. If you do not yet have one, you can get an account here: https://github.com/join. Once you create your account, you may want to get the Student Developer Pack, which will give you access to a lot of other features (please note that having the Student Developer Pack is not necessary for CAPP 30121; it’s just a nice benefit you get as a student.)
Joining the uchicago-CAPP30121-aut-2021 organization¶
We will be using GitHub Classroom and have created a GitHub organization (uchicago-CAPP30121-aut-2021) for the course (a GitHub “organization” is basically a way to group together related repositories). You should have received email to your UChicago email account with an invitation to join the organization. If you have already accepted the invitation, then you can move on to the next section. If you have not already accepted the invitation, please open the Classroom URL listed on #camp-21 Slack message, log into GitHub if necessary, and then accept the invitation. If run into any trouble, please ask for help.
Creating a GitHub Personal Access Token¶
GitHub uses two mechanisms for authenticating yourself: Personal Access Tokens and SSH Keys. GitHub recommends using personal access tokens, so that’s what we will use for this class.
Please go to this page and create a personal access token (hereafter referred to as your PAT).
You will need to save this token for future use. If you regularly use a password manager that has a web interface (for easy access when you want to work in CSIL and do not have your laptop with you), we recommend adding your PAT to your password manager. Otherwise, you can save it in a file in your home directory and then set the permissions on the file to user read-only using the command:
chmod 400 FILENAME
where FILENAME is replaced with the name of the file that holds your
PAT. (Run man chmod
or see the permissions section of the
linux_lab Lab for an explanation of the chmod
command.)
To avoid having Git ask for your credentials every time you interact with the server, you can ask it to “remember” your PAT for some set amount of time. This means that, once you enter your PAT, Git will not ask for it again for some amount of time (by default, this will be 15 minutes). To enable this feature, run the following command:
git config --global credential.helper cache
You can set a longer timeout with this command:
git config --global credential.helper 'cache --timeout=3600'
(the timeout is in seconds, which means the above command will make Git remember your password for one hour)
Please run these commands now. You won’t need to run these commands
again on a CS machine, because they record information in a
configuration file, named .gitconfig
, in your home directory for
future use.
Please note that you’ll be asked for your PAT the first time you run a command that interacts with the GitHub server , but then should be set for the rest of this lab session. Every time you start work, you’ll need to enter your PAT the first time you interact with the server and then not again until your credentials time out.
Creating your first repository¶
For each assignment in CAPP 30121, we will provide you with an invitation URL
that will allow you sign up for the assignment on GitHub and which
will result in the creation of a repository called
XX-GITHUB_USERNAME
inside our uchicago-CAPP30121-aut-2021
organization
on GitHub. For example, if your GitHub username is
jrandom
and XX is camp-1
, your repository will be called camp-1-jrandom
. This
repository will be private, and can only be viewed by you and the CAPP 30121 course staff.
For this lab, use the CAMP-1 URL that we supplied on Slack. When you open the invitation URL in a browser tab, you will have to complete the following steps:
You will need to select your name (and CnetID) from a list. This step will allow us to know what student is associated with each GitHub account. This step is only done for the very first assignment invitation you accept.
You must click “Accept this assignment” or your repository will not actually be created.
If you run into any issues, please ask for help.
Initializing your repository¶
You will start by initializing your repository. Your repository is hosted on GitHub, but you can create a local copy in your home directory (we will refer to this as your local repository).
Log into https://github.com/. Your homework repository,
uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME
should appear
under “Repositories” on the left side of the page. (If you don’t see
a list of repositories on the left side of the page, try clicking on
the GitHub Cat logo.) Clicking on this link will take you to a page
where you can browse your repository through GitHub’s web
interface. Since you haven’t initialized your repository yet, GitHub
will provide you with the instructions to initialize your
repository. You can ignore those instructions. Instead, do the
following:
Create a directory in your home directory for CAPP 30121. The name and location of this directory is not important, so if you have a very strong preference for a different directory structure, you’re welcome to use it. Otherwise, we suggest you simply do this:
cd mkdir -p capp30121/camp-1-GITHUB-USERNAME cd capp30121/camp-1-GITHUB-USERNAME
replacing GITHUB-USERNAME with your GitHub username.
(the
-p
flag to mkdir will create all the parent directories if needed; i.e., if you don’t already have acapp30121
directory, it will create one, and then will create acamp-1-GITHUB-USERNAME
directory inside it)Navigate to the folder you just created, create a file called
README.md
, and add your full name to the file using an editor. You can create a new file using VSCode by runningcode <filename>
in a terminal window that is the opened in appropriate directory. (Recall that the notation<filename>
is a placeholder that should be replaced with an acutal filename.) For this specific task, can use the commandcode README.md
.Run the commands below replacing
GITHUB_USERNAME
in the fifth command with your GitHub username. We encourage you to run these commands one at a time and to only move on to the next command when you are sure the first one succeeded.git init git add README.md git commit -m "first commit" git branch -M main git remote add origin https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME.git git push -u origin main
If a command asks you to enter a username and PAT, just enter your GitHub username and the PAT you created earlier (do not enter your CNetID and password)
Don’t worry about what each individual command does; we will be seeing what most of these commands do in this lab. If you encounter any error messages, please do make sure to let us know.
You can verify that your repository was correctly set up by going back
to your repository’s page on GitHub, you should now see it contains a
README.md
file. If you click on it, you can see its contents.
Creating a commit¶
If you make changes to your repository, the way to store those changes (and the updated versions of the modified files) is by creating a commit. So, let’s start by making some changes:
Edit
README.md
to also include your CNetID on the same line as your nameCreate a new file called
test.txt
that contains a single line with the textHello, world!
Creating a commit is a two-step process. First, you have to indicate
what files you want to include in your commit. Let’s say we want to
create a commit that only includes the updated README.md
file. We
can specify this operation explicitly using the git add
command from
the terminal:
git add README.md
This command will not print any output if it is successful.
To create the commit, use the git commit
command. This command will
take all the files you added with git add
and will bundle them into
a commit:
git commit -m "Updated README.md"
The text after the -m
is a short message that describes the changes
you have made since your last commit. Common examples of commit messages
might be “Finished homework 1” or “Implemented insert function for data
struct”.
Warning
If you forget the -m
parameter, Git will think that
you forgot to specify a commit message. It will graciously open up a
default editor so that you can enter such a message. This can be useful
if you want to enter a longer commit message (including multi-line
messages). We will experiment with this later.
Once you run the above command, you will see something like the following output:
[main 3e39c15] Updated README.md
1 file changed, 1 insertion(+), 1 deletion(-)
You’ve created a commit, but you’re not done yet: you haven’t uploaded
it to GitHub yet. Forgetting this step is actually a very common
pitfall, so don’t forget to upload your changes. You must use the
git push
command for your changes to be uploaded to the Git
server. If you don’t, the course staff will not be able to see your work.
Simply run the following command from the Linux command-line:
git push
You may be asked for your GitHub username and PAT; once you enter them, you should see something like this output:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 279 bytes | 279.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME.git
392555e..0c85752 main -> main
You can ignore most of those messages. The important thing is to not see any warnings or error messages.
Warning
When you push for the first time, you may get a message
saying that push.default is unset
, and suggesting two possible
commands to remedy the situation. While the rest of the commands in this homework
will work fine if you don’t run either of these commands, you should run the
command to use “simple” (this will prevent the warning from appearing
every time you push)
You can verify that your commit was correctly pushed to GitHub by
going to your repository on the GitHub website. The README.md
file should now
show the updated content (your name and CNetID)
In general, if you’re concerned about whether the course staff are seeing the right version of your work, you can just go to GitHub. Whatever is shown on your repository’s page is what the course staff will see. If you wrote some code, and it doesn’t show up on GitHub, make sure you didn’t forget to add your files, create a commit, and push the most recent commit to the server.
git add
revisited and git status
¶
Let’s make a further change to README.md
: Add a line with the text
CAPP 30121 - Computer Science with Applications 1
.
So, at this point, we have a file we have already committed
(README.md
) but where the local version is now out of sync with
the version on GitHub. Furthermore, earlier we created a test.txt
file. Is it a part of our repository? You can use the following command
to ask Git for a summary of the files it is tracking:
git status
This command should output something like this:
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
no changes added to commit (use "git add" and/or "git commit -a")
Note
When working on CS machines, you should see the message above. At
some point, you will start using git with your own machine.
depending on the version of Git you have installed, the message
under Changes not staged for commit
may refer to a command
called git checkout
(instead of git restore
).
Notice that there are two types of files listed here:
Changes not staged for commit
: This is a list of files that Git knows about and have been modified since your last commit, but which have not been added to a commit (withgit add
). Note that we did usegit add
previously withREADME.md
(which is why Git is “tracking” that file), but we have not rungit add
since our last commit, which means the change we made toREADME.md
is not currently scheduled to be included in any commit. Remember: committing is a two-step process (yougit add
the files that will be part of the commit, and then you create the commit).Untracked files
: This is a list of files that Git has found in the same directory as your repository, but which Git isn’t tracking.
Warning
You may see some automatically generated files in your Untracked files section. Files that start with a pound sign (#) or end with a tilde should not be added to your repository. Files that end with a tilde are backup files created by some editors that are intended to help you restore your files if your computer crashes. In general, files that are automatically generated should not be committed to your repository. Other people should be able to generate their own versions, if necessary.
So, let’s go ahead and add README.md
:
git add README.md
And re-run git status
. You should see something like this:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
Note
When working on CS machines, you should see the message above.
When using your git on own machine and depending on the version of
Git you have installed, the message under Changes to be
committed
may refer to a command called git reset
(instead of
git restore
).
Notice how there is now a new category of files:
Changes to be committed
. Adding README.md
not only added the
file to your repository, it also staged it into the next commit (which,
remember, won’t happen until you actually run git commit
).
If we now add test.txt
:
git add test.txt
The output of git status
should now look like this:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
new file: test.txt
Now, we are going to create a commit with these changes. Notice how we
are not going to use the -m
parameter to git commit
:
git commit
When you omit -m
, Git will open a terminal text editor where you can
write your commit message, including multi-line commit messages. By
default, the CS machines will use nano for this.
You should see something like this:
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Your branch is up to date with 'origin/main'.
#
# Changes to be committed:
# modified: README.md
# new file: test.txt
#
Now, type in the following commit message above the lines that start with #
:
CAPP Camp Lab 2 updates:
- Added test.txt
- Updated README.md file
In nano, you can save the file and exit by pressing Control-X, entering “Y” when prompted to “save modified buffer” (i.e., whether to save the file before exiting), and then Enter (you may be presented with a new set of menu options; just press Enter).
This will complete the commit, and you will see a message like this:
[main 1810c54] Camp 1 updates:
2 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 test.txt
Note
If you want to change your default command-line editor, add a line like this:
export EDITOR=myfavoriteeditor
At the end of the .bashrc
file in your home directory (make sure you
replace myfavoriteeditor
with the command for your favorite
command-line editor: vi
, emacs
, nano
, mcedit
, etc.)
Now, edit README.md
and test.txt
and add an extra line to each of them with the text
Git is pretty cool
. Running git status
should now show the
following:
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
modified: test.txt
If we want to create a commit with these changes, we could simply run
git add README.md test.txt
, but this can get cumbersome if we want to
add a lot of files. Fortunately, we can also do
this:
git add -u
This command will add every file that Git is tracking, and will ignore untracked
files. There are a few other shortcuts for adding multiple files, like
git add .
and git add --all
, but we strongly suggest you avoid them,
since they can result in adding files you did not intend to add to your
repository.
So, if you run git add -u
and create a commit:
git commit -m "A few more changes"
git status
will now show this:
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
The message Your branch is ahead of 'origin/main' by 2 commits.
is
telling you that your local repository contains two commits that have
not yet been uploaded to GitHub. In fact, if you go to your repository
on the GitHub website, you’ll see that the two commits we just created
are nowhere to be seen. As helpfully pointed out by the above output,
all we need to do is run git push
, which should show something like
this:
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 16 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (8/8), 728 bytes | 728.00 KiB/s, done.
Total 8 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME.git
0c85752..e3f9ef1 main -> main
Now go to GitHub. Do you see the updates in your repository? Click on “Commits” (above the file listing in your repository). If you click on the individual commits, you will be able to see the exact changes that were included in each commit.
Now, git status
will look like this:
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
If you see nothing to commit, working tree clean
, that means
that there are no changes in your local repository since the last commit
you created (and, additionally, the above output also tells us that all
our commits have also been uploaded to GitHub)
Working from multiple locations¶
So far, you have a local repository in your CS home directory, which you
have been uploading to GitHub using the git push
command. However,
if you work from multiple locations (e.g., on a CS machine but also from
your laptop), you will need to be able to create a local repository in
those locations too. You can do this by running the git clone
command (don’t run this command just yet):
git clone https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME.git
This will create a local repository that “clones” the version of the repository that is currently stored on GitHub.
For the purposes of this lab, we’ll create this second copy in a
separate directory of the same machine where you’ve been running Git
commands so far. Open a second terminal window (try using the
keyboard shortcut Ctrl+Alt+t.
to create the window), and run these
commands in the new window:
mkdir -p /tmp/$USER/capp30121
cd /tmp/$USER/capp30121
git clone https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME.git
(FYI: USER
is a bash environment variable that is set
automatically to your user name. Bash will replace $USER
in the command with your
CS login.)
Make sure to replace GITHUB_USERNAME
with your GitHub username!
Take into account that, when you run git clone
, the repository is
not cloned into the current directory. Instead, a new directory
(with the same name as the repository) will be created in the current
directory, and you will need to cd
into it to use Git commands for
that repository.
You now have two local copies of the repository: one in your home
directory (/home/USER/capp30121/camp-1-GITHUB-USERNAME
), which refer to as your
home repository for now and one in /tmp
(/tmp/USER/capp30121/camp-1-GITHUB_USERNAME
) which we will
refer to as your temp repository.
Now, switch to the window that is open to your home repository, add a
line to test.txt
with the text One more change!
. Create a
commit for that change and push it to GitHub (you should know how to
do this by now, but make sure to ask for help if
you’re unsure of how to proceed). Also, you don’t have to use any
specific commit message (unlike previous steps where we gave you the
exact message), but make sure your commit message is descriptive and
to the point.
Next, switch to the window that is open to your temp repository, check
if that change appears in the test.txt
file. It will not, because
you have not yet downloaded the latest commits from the
repository. You can do this by running this command:
git pull
This should output something like this:
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 312 bytes | 20.00 KiB/s, done.
From https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB_USERNAME
e3f9ef1..5716877 main -> origin/main
Updating e3f9ef1..5716877
Fast-forward
test.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
If you have multiple local repositories (e.g., one on a CS machine and
one on your laptop), it is very important that you remember to run
git pull
before you start working, and that you git push
any
changes you make. Otherwise, your local repositories (and the repository
on GitHub) may diverge leading to a messy situation called a merge
conflict (we discuss conflicts in more detail below). This will be
specially important once you start using Git for its intended purpose:
to collaborate with multiple developers, where each developer will have
their own local repository, and it will become easier for some
developers’ code to diverge from others’.
Discarding changes and unstaging¶
One of the benefits of using a version control system is that it is very
easy to inspect the history of changes to a given file, as well as to
undo changes we did not intend to make. For example, edit test.txt
to remove all its contents. git status
will tell us this:
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
If we want to discard the changes we made to test.txt
, all we have
to do is follow the helpful advice provided by the above output:
git restore test.txt
Note
In older versions of Git, git status
may refer to the git checkout
command.
In that case, run this command instead:
git checkout -- test.txt
If you open test.txt
, you’ll see that its contents have been
magically restored!
Now, edit test.txt
and README.md
to add an additional line with
the text Hopefully our last change...
. Run git add -u
but don’t
commit it just yet. git status
will show this:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
modified: test.txt
Now, let’s say we realized we want to commit the changes to
README.md
, but not to test.txt
. However, we’ve already told git
that we want to include test.txt
in the commit. Fortunately, we can
“un-include” it (or “unstage” it, in Git lingo) by running this:
git restore --staged test.txt
Note
In older versions of Git, git status
may refer to the git reset
command.
In that case, run this command instead:
git reset HEAD test.txt
Now, git status
will show the following:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
Go ahead and run git commit
. The commit will now include only
README.md
.
Before moving on to the next part of the lab, let’s make sure all our changes have been committed and pushed:
git add -u
git commit -m"Wrapping up staging part of the lab"
git push
Before continuing, make sure git status
shows this:
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Looking at the commit log¶
Once you have made multiple commits, you can see these commits, their
dates, commit messages, author, etc. by typing git log
. This command
will open a scrollable interface (using the up/down arrow keys) that you
can get out of by pressing the q
key. As we saw earlier, you can
also see the history of commits through on GitHub’s web interface, but
it is also useful to be able to access the commit log directly from the
terminal, without having to open a browser.
Each commit will have a commit hash (usually referred to as the commit SHA) that looks something like this:
9119c6ffcebc2e3540d587180236aaf1222ee63c
This is a unique identifier that we can use to refer to that commit elsewhere. For example, choose any commit from the commit log and run the following:
git show COMMIT_SHA
Make sure to replace COMMIT_SHA
with a commit SHA that appears in
your commit log.
This will show you the changes that were included in that commit. The
output of git show
can be a bit hard to parse at first but the most
important thing to take into account is that any line starting with a
+
denotes a line that was added, and any line starting with a -
denotes a line that was removed.
Pro tip: in any place where you have to refer to a commit SHA, you can
just write the first few characters of the commit SHA. For example, for
commit 9119c6ffcebc2e3540d587180236aaf1222ee63c
we could write just
this:
git show 9119c6f
Git will only complain if there is more than one commit that starts with that same prefix.
Merge conflicts¶
If you have multiple copies of the same repository, it is easy for
them to get out of sync. In this section, we will purposely create a
merge conflict using the home and temp repositories that you have
created to allow you to see how to fix conflicts. As in the
section on working from multiple locations, you’ll want to have
two windows open for this section: one where you’ll work with your home
repository (that is, the copy of the repository in your home
directory) and the other where you’ll work with your temp repository
(the one in /tmp
).
First, let’s add a file to your home repository. Use pwd
to make
sure you are in the right local copy the repository:
$ pwd
/home/USER/capp30121/camp-1-GITHUB-USERNAME
(USER will be your CNetID.) If the result of pwd
starts with
/tmp
then you are in the wrong window and should switch to the
correct one before proceeding.
Open an editor and create a file named balloons.py
(code
balloons.py
) that contains these four lines of Python code:
print("Let's get started.")
print("How many red balloons were released?")
print("99 red balloons!")
print("All done.")
Now add, commit, and push this code to the server.
Switch to the window open to the temp copy of your repository and run
ls
. Do see balloons.py
? No. Why? Because the temp copy of
the repository is out of sync with the server. Run:
git pull
to get it back in sync.
To create a merge conflict, we need to edit files in different and
conflicting ways. In the temp copy of the repository, replace both
occurrences of red
with green
:
print("Let's get started.")
print("How many green balloons were released?")
print("99 green balloons!")
print("All done.")
Now add, commit, and push this code to the repository.
Switch back to the home copy of your repository (/home/USER/capp30121/camp-1-capp30121/camp-1-GITHUB-USERNAME
). The home copy is out of sync with the server and the temp copy, but do not pull from the server to sync them up just yet. Instead, change red
to blue
in balloons.py
:
print("Let's get started.")
print("How many blue balloons were released?")
print("99 blue balloons!")
print("All done.")
and then add and commit the file to this copy of your repository. If you try to push at this point, you’ll see a message like this:
$ git push
To https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB-USERNAME.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB-USERNAME.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
The hint says to do a git pull
, let’s try that:
$ git pull
Auto-merging balloons.py
CONFLICT (content): Merge conflict in balloons.py
Automatic merge failed; fix conflicts and then commit the result.
Git recorded the conflicts in balloons.py
and it is our
responsibility to resolve them before we proceed.
The file is small, so we can use cat
to look at the contents:
$ cat balloons.py
print("Let's get started.")
<<<<<<< HEAD
print("How many blue balloons were released?")
print("99 blue balloons!")
=======
print("How many green balloons were released?")
print("99 green balloons!")
>>>>>>> 722bcb5b1b8e815f895f7256536f38e6d1a71c53
print("All done.")
The long number 722bcb5b1b8e815f895f7256536f38e6d1a71c53
is the
SHA for our commit. You’ll see a different number there.
We need to resolve this conflict and remove the conflict markings (“<<<”, “===”, etc). In some cases, resolving the conflict will just involve editing the file to keep the exact code in one of the two versions. However, we are not required to do so. For example, the developer handling this merge conflict may look at this code and decide that red is the right color for the balloons after all. In that case, we would just replace the conflict with this code:
print("How many red balloons were released?")
print("99 red balloons!")
To make this change, open the file in an editor (code balloons.py
)
remove/update the relevant lines, and save your changes. When you are
done, the file balloons.py
should contain the following:
print("Let's get started.")
print("How many red balloons were released?")
print("99 red balloons!")
print("All done.")
Now, we need to tell Git that we’ve resolved the merge conflict. We do
this by using git add
:
git add balloon.py
Note how now git status
recognizes that the merge conflict has been
resolved, but has yet to be committed:
$ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: balloons.py
So, all we need to do is to run this command:
git commit
which will open up an editor with a default commit message like:
Merge branch 'main' of https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB-USER into main
You could change this to something like Merging (balloons should
actually be red)
to indicate that you did not actually accept the
changes from either version. For now you can leave it as it and just
save the file. Once you save the commit message, the merge will be
completed and you will see something like this:
[main 8e0f408] Merge branch 'main' of https://github.com/uchicago-CAPP30121-aut-2021/camp-1-GITHUB-USER into main
Before continuing with the rest of the lab, make sure to git push
your work. You might also want to run git pull
in your temp repo
to bring it up to date with the server.
Working with upstream repositories¶
For each assignment, we provide some initial code that you must upload to your repository. We’ll use what is known as an upstream repository to distribute this code.
We have created a second assignment for you to gain practice with this process.
We’ll follow steps similar to what you did at the beginning of this lab with a couple of extra commands thrown in.
Using a browser, accept the invitation at the CAMP-2 URL that we supplied on Slack.
Navigate to your
/home/USER/capp30121
directory and creating a new directory namedcamp-2-GITHUB-USERNAME
(where, as usual, GITHUB-USERNAME is replaced with your GITHUB-USERNAME).cd ~/capp30121 mkdir camp-2-GITHUB-USERNAME cd camp-2-GITHUB-USERNAME
And then run the following commands using your GitHub username in place of
GITHUB_USERNAME
in the second command.git init git remote add origin https://github.com/uchicago-CAPP30121-aut-2021/camp-2-GITHUB_USERNAME.git git remote add upstream https://github.com/uchicago-CAPP30121-aut-2021/camp-2-initial-code.git git pull upstream main git branch -M main git push -u origin main
If you run an
ls
, you will see that your directory now contains two files:hello.py README.md
If you are wondering, here is what these commands do (line-by-line):
Initialize a local repository
Connect the local repository to the repository that was created for you on GitHub when you accepted the invitation.
Connect your local repository to an upstream GitHub repository that we have seeded with code for this assignment.
Pull the seed code from the upstream repository into your local copy of the repository and package it into a commit. Notice that the pull command indicates that code should be pulled from the
main
branch of the upstream repository.Renames the branch for your local repository from
master
, a legacy name, tomain
, the preferred name.Push the current commit to GitHub. The arguments
-u origin main
tell Git that you want to push from the local copy (origin
) to themain
branch on GitHub. Git will remember and reuse these parameters when you rungit push
from this copy of the repository in the future.
From here on out, you can add, commit, pull, and push as usual to
manage your repository. In the (hopefully) unlikely event that we
need to fix a bug in the code that we provide, we’ll update the
upstream repository and ask you to run git pull upstream main
, to
pull changes to the upstream code into your local copy.
Acknowledgments¶
Many CS 121 instructors and TAs have worked on this lab over the years. Gustav Larsson (PhD ‘17) and Isha Mehrotra (SB’19) deserve special mention. Gustav wrote the original version of this lab and Isha wrote the original material on branches and merge conflicts.