Content from Setup Instructions


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • What software do I need to have installed?
  • Do I have a GitHub account?

Objectives

  • Install VS Code and other needed software
  • Connect VS Code to GitHub

Callout

If you are participating in this workshop remotely (e.g. over Zoom), it is highly recommended that you use two screens: 1 screen with the remote meeting, to see the instructor sharing their screen, and 1 screen with your applications. You will need to have VS Code and a web browser open to GitHub.com in order to follow along.

Example Screen setup
Example Screen setup

Create a GitHub account


If you do not already have a GitHub account, visit github.com to create one.

You can refer to this doc page for further instructions about creating a GitHub account.

If you already have a GitHub account, please verify that you can sign in, and take note of the email(s) associated with the account.

It is strongly recommended that you set up 2FA for your GitHub account, and to use a password manager.

Software Installations


Visual Studio Code

Download and install VS Code.

If you are new to using VS Code, you can review this Getting Started guide.

Git

You must have Git installed on your local computer. Typically, Mac and Linux computers come pre-installed with git, while Windows users must install GitBash (Git for Windows). However, you should verify that Git is installed on your computer.

You can verify git is installed by opening a command line application (e.g. Terminal) and typing:

BASH

$ git version

If you see an error message stating git is an unknown command, you will need to install git.

If you do not already have git installed, you can refer to this GitHub guide on installing git for any OS.

Bash

You should have a Bash terminal. If you are on a Windows, you will have a Bash terminal by virtue of installing Git for Windows (GitBash). If you are on a Mac or Linux, you will already have a Bash terminal. If you prefer, you can use a similar terminal like Zsh.

Rather than using a seperate command line application, you will be using the Terminal in VS Code. To learn more about using the Terminal in VS Code, refer to these docs.

Connect VS Code to GitHub


Please refer to these instructions to sign in to GitHub from VS Code.

Optionally, you can install the GitHub extension, and follow these instructions to sign into GitHub.

Key Points

  • GitHub, VS Code, bash, and git are needed for this lesson

Content from Introduction to Git & GitHub


Last updated on 2025-04-07 | Edit this page

Overview

Questions

  • What is Git?
  • What is GitHub?

Objectives

  • recognize why version control is useful
  • distinguish between Git and GitHub

What is Version Control?


Version control is a name used for software which can help you record changes you make to the files in a directory on your computer. Version control software and tools (such as Git and Subversion/SVN) are often associated with software development, and increasingly, they are being used to collaborate in research and academic environments. Version control systems work best with plain text files such as documents or computer code, but modern version control systems can be used to track changes in most types of file.

At its most basic level, version control software helps us register and track sets of changes made to files on our computer. We can then reason about and share those changes with others. As we build up sets of changes over time, we begin to see some benefits.

Benefits of using version control?

  • Collaboration - Version control allows us to define formalized ways we can work together and share writing and code. For example merging together sets of changes from different parties enables co-creation of documents and software across distributed teams.
  • Versioning - Having a robust and rigorous log of changes to a file, without renaming files (v1, v2, final_copy)
  • Rolling Back - Version control allows us to quickly undo a set of changes. This can be useful when new writing or new additions to code introduce problems.
  • Understanding - Version control can help you understand how the code or writing came to be, who wrote or contributed particular parts, and who you might ask to help understand it better.
  • Backup - While not meant to be a backup solution, using version control systems mean that your code and writing can be stored on multiple other computers.

There are many more reasons to use version control, and we’ll explore some of these in the library context, but first let’s learn a bit about a popular version control tool called Git.

Piled Higher and Deeper by Jorge Cham, http://www.phdcomics.com/comics/archive_print.php?comicid=1531

“Piled Higher and Deeper” by Jorge Cham, http://www.phdcomics.com

What are Git and GitHub?


We often hear the terms Git and GitHub used interchangeably but they are slightly different things.

Git is one of the most widely used version control systems in the world. It is a free, open source tool that can be downloaded to your local machine and used for logging all changes made to a group of designated computer files (referred to as a “git repository” or “repo” for short) over time. It can be used to control file versions locally by you alone on your computer, but is perhaps most powerful when employed to coordinate simultaneous work on a group of files shared among distributed groups of people.

Rather than emailing documents with tracked changes and some comments and renaming different versions of files (example.txt, exampleV2.txt, exampleV3.txt) to differentiate them, we can use Git to save (or in Git parlance, “commit”) all that information with the document itself. This makes it easy to get an overview of all changes made to a file over time by looking at a log of all the changes that have been made. And all earlier versions of each file still remain in their original form: they are not overwritten, should we ever wish to “roll back” to them.

Git was originally developed to help software developers work collaboratively on software projects, but it can be and is used for managing revisions to any file type on a computer system, including text documents and spreadsheets. Once installed, interaction with Git is done through the Command Prompt in Windows, or the Terminal on Mac/Linux. Since Word documents contain special formatting, Git unfortunately cannot version control those, nor can it version control PDFs, though both file types can be stored in Git repositories.

GitHub on the other hand is a popular website for hosting and sharing Git repositories remotely. It offers a web interface and provides functionality and a mixture of both free and paid services for working with such repositories. The majority of the content that GitHub hosts is open source software, though increasingly it is being used for other projects such as open access journals (e.g. Journal of Open Source Software), blogs, and regularly updated text books. In addition to GitHub, there are other Git hosting services that offer many similar features such as GitLab, Bitbucket and Gitee.

Visualizing Git

Version control systems start with a base version of the document and then save just the changes you made at each step of the way. You can think of it as a tape: if you rewind the tape and start at the base document, then you can play back each change and end up with your latest version.

Changes Are Saved Sequentially
Changes Are Saved Sequentially

Once you think of changes as separate from the document itself, you can then think about “playing back” different sets of changes onto the base document and getting different versions of the document. For example, two users can make independent sets of changes based on the same document.

Different Versions Can be Saved
Different Versions Can be Saved

Unless there are conflicts, you can even play two sets of changes onto the same base document.

Multiple Versions Can be Merged
Multiple Versions Can be Merged

Git terminology


One of the main barriers to getting started with Git is understanding the terminology necessary to executing commands. Although some of the language used in Git aligns with common-use words in English, other terms are not so clear. The best way to learn Git terminology - which consists of a number of verbs such as add, commit and push (preceded by the word ‘git’) - is to use it, which is what we will be doing during this lesson. We will explain these commands as we proceed from setting up a new version-controlled project to publishing our own website.

On a command line interface, Git commands are written as git verb options, where verb is what we actually want to do and options is additional optional information which may be needed for the verb.

Key Points

  • Version control helps track changes to files and projects
  • Git and GitHub are not the same
  • Git commands are written as git verb options

Content from Create a GitHub Repository


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • How do I create a new repository on GitHub?
  • How do I clone the repository to my local computer?

Objectives

  • Create multiverse repository on GitHub
  • Clone the multiverse repository using VS Code

Create a new repo on GitHub


The first thing we need to do is create a new repository. While you can create repositories locally, and never even connect the local repo to a remote repo (hosted on a site like GitHub), the simplist and most common pattern to first create a new repo on GitHub, and then clone that repo to your local computer.

You should already be signed in to GitHub. You can create a new repo from anywhere on the site by clicking on the “+” icon in the upper right, and then clicking “New Repository”:

Create a new repo from anywhere in GitHub
Create a new repo from anywhere in GitHub

Select your Github username as the “owner”.

Type multiverse for the repository name.

Check the box next to “Add a README file”.

Leave all other options as the default - your repo should be public, no gitignore selected, no license selected, and no template selected.

Create the multiverse repo in GitHub
Create the multiverse repo in GitHub

Finally, click the green “Create Repository” button at the bottom right.

You will be redirected to your newly created and empty multiverse repo.

Your new multiverse repo on GitHub
Your new multiverse repo on GitHub

Clone your multiverse repo to your local computer


Now that the multiverse repo has been created, we can “clone” it (get a local copy of the repo) through VS Code.

Make sure you have a new VS Code window open. If you already have a repo/folder open in VS Code, go to the “File” menu and click “New window”.

In your new VS Code window, go to the “Source Control” pane (the 3rd one down). Click “Clone Repository”, and then click “Clone from GitHub”.

Clone a GitHub repo in VS Code
Clone a GitHub repo in VS Code

If you don’t immediately see your multiverse repo, you can search for it by typing “multiverse” in the search box. When you see your multiverse repo (it should have your username in the URL), click it.

Clone your multiverse repo via VS Code
Clone your multiverse repo via VS Code

You will now need to choose where on your local computer the multiverse repo will live. You can choose any easily accessible location, such as the “Desktop” folder. It is standard practice to save all local repos in a folder named “GitHub” in your “Documents” folder.

Click “Open” when prompted to open the newly cloned multiverse repo.

Open a Bash Terminal in VS Code


Now that you have your multiverse repo cloned and open in VS Code, the last step is to open a bash terminal.

To see the terminal pane, go to the “Terminal” menu, and click “New terminal”.

If you are on a Windows computer, you will need to specifically open a GitBash terminal. Find the “+” icon in the terminal pane, and click the carrot dropdown icon next to it. Click “GitBash”.

Open a GitBash terminal if on Windows
Open a GitBash terminal if on Windows

If you are on a Mac or Linux computer, your default terminal should be sufficient. You can also choose to open a Bash terminal by following the same instructions.

You should now have your empty multiverse repo open, with a Bash terminal open, and you are ready to start typing your first git commands!

Ready to begin
Ready to begin

Key Points

  • Create a new repository on GitHub
  • Clone the repository to your local computer
  • Open the terminal in VS Code

Content from Setup Git Configs


Last updated on 2025-05-19 | Edit this page

Overview

Questions

  • How do I first set up Git?

Objectives

  • set up basic configs for Git

Setting up Git


When we use Git on a new computer for the first time, we need to configure a few things. Some basic configurations to set for Git are:

  • your name
  • your email address,
  • your preferred text editor

To start we will check in on our current Git configuration. Open your shell terminal window and type:

BASH

$ git config --list

First, we will tell Git our user name and email.

Please note: You need to use the same email address in your Git configuration in the shell as you entered into GitHub when you created your GitHub account. Later in the lesson we will be using GitHub and the email addresses need to match. If you are concerned about privacy, please review GitHub’s instructions for keeping your email address private.

Type these two commands into your shell, using your own name and email:

BASH

$ git config --global user.name "Loki Odinson"
$ git config --global user.email "loki.odinson@tva.org"

If you enter the commands correctly, the shell will merely return a command prompt and no messages. To check your work, ask Git what your configuration is using the same command as above:

Let’s also set our default text editor. A text editor is necessary with some of your Git work, and the default from Git is Vim, which is a text editor that is hard to learn at first. Since we are using VS Code for this lesson, we will set the default editor to code. You can feel free to change this at a later time.

BASH

$ git config --global core.editor "code --wait"

BASH

git config --list

OUTPUT

user.name=Loki Odinson
user.email=loki.odinson@tva.org
core.editor=code --wait

Line Endings

As with other keys, when you hit the ‘return’ key on your keyboard, your computer encodes this input. For reasons that are long to explain, different operating systems use different character(s) to represent the end of a line. (You may also hear these referred to as newlines or line breaks.) Because git uses these characters to compare files, it may cause unexpected issues when editing a file on different machines.

You can change the way git recognizes and encodes line endings using the core.autocrlf command to git config. The following settings are recommended:

On OS X and Linux:

BASH

$ git config --global core.autocrlf input

And on Windows:

BASH

$ git config --global core.autocrlf true

You can read more about this issue on this GitHub page.

Default Git branch naming

BASH

$ git config --global init.defaultBranch main

Source file changes are associated with a “branch.” By default, Git will create a branch called master when you create a new repository with git init. This term evokes the racist practice of human slavery and the software development community has moved to adopt more inclusive language.

In 2020, most Git code hosting services transitioned to using main as the default branch. As an example, any new repository that is opened in GitHub and GitLab default to main. However, Git has not yet made the same change. As a result, local repositories must be manually configured have the same main branch name as most cloud services.

For versions of Git prior to 2.28, the change can be made on an individual repository level. Note that if this value is unset in your local Git configuration, the init.defaultBranch value defaults to master.

Since we are creating the repository on GitHub, the default branch name for the multiverse repo will be main. Configure this setting if you plan on creating git repositories locally first.

Key Points

  • Version control helps track changes to files and projects
  • Git and GitHub are not the same
  • Git commands are written as git verb options
  • When we use Git on a new computer for the first time, we need to configure a few things

Content from Tracking Changes


Last updated on 2025-05-19 | Edit this page

Overview

Questions

  • How do I record changes in Git?
  • How do I check the status of my version control repository?
  • How do I record notes about what changes I made and why?

Objectives

  • Go through the modify-add-commit cycle for one or more files.
  • Explain where information is stored at each stage of that cycle.
  • Distinguish between descriptive and non-descriptive commit messages.

Loki writes a story about Thor in New Asgard


Loki, in his role as God of Stories, oversees the many branching timelines in the multiverse. But even an infinitely clever being like Loki has trouble keeping track of all of the events across the multiverse. Fortunately, there is a tool that can help keep track of these events across different timeline branches: git! Loki has decided to start logging events in a git repository named multiverse. Each planet will have their own file. Loki starts recording the events of New Asgard on Earth, where his brother Thor lives.

Create a file


First let’s make sure we’re in the right directory. You should be in the multiverse directory.

BASH

$ pwd

Let’s create a file called earth.txt to start recording the events taking place on the planet Earth.

Make sure you have the Explorer pane open in VS Code, and click the “New File” button. Name the file earth.txt.

Type the text below into the earth.txt file:

OUTPUT

Thor defends New Asgard from invaders.

Make sure to end the file with a newline!

Save the file.

Track Changes to the File


If we check the status of our project again, Git tells us that it’s noticed the new file:

BASH

$ git status

OUTPUT

On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        earth.txt

nothing added to commit but untracked files present (use "git add" to track)

The “untracked files” message means that there’s a file in the directory that Git isn’t keeping track of. We can tell Git to track a file using git add:

BASH

$ git add earth.txt

and then check that the right thing happened:

BASH

$ git status

OUTPUT

On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   earth.txt

Git now knows that it’s supposed to keep track of earth.txt, but it hasn’t recorded these changes as a commit yet. To get it to do that, we need to run one more command:

BASH

$ git commit -m "Start story for New Asgard in earth.txt"

OUTPUT

[main 9b26458] Start story for New Asgard in earth.txt
 1 file changed, 1 insertion(+)
 create mode 100644 earth.txt

When we run git commit, Git takes everything we have told it to save by using git add and stores a copy permanently inside the special .git directory. This permanent copy is called a commit (or revision) and its short identifier is 9b26458 (Your commit will have another identifier.)

We use the -m flag (for “message”) to record a short, descriptive, and specific comment that will help us remember later on what we did and why. If we just run git commit without the -m option, Git will launch a VS Code window (or whatever other editor we configured as core.editor) so that we can write a longer message.

Good commit messages start with a brief (<50 characters) summary of changes made in the commit. If you want to go into more detail, add a blank line between the summary line and your additional notes.

If we run git status now:

BASH

$ git status

OUTPUT

On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

It tells us everything is up to date. If we want to know what we’ve done recently, we can ask Git to show us the project’s history using git log:

BASH

$ git log

OUTPUT

commit 9b26458f5d229d48be61023bcb510f8beb3f13db (HEAD -> main)
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 20:18:55 2025 -0400

    Start story for New Asgard in earth.txt

commit f537d84c6ef9b6d988f642400b2017f855f9aaa1 (origin/main, origin/HEAD)
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 18:34:45 2025 -0400

    Initial commit

git log lists all commits made to a repository in reverse chronological order. The listing for each commit includes the commit’s full identifier (which starts with the same characters as the short identifier printed by the git commit command earlier), the commit’s author, when it was created, and the log message Git was given when the commit was created

Make more changes to the file


Now suppose Loki records another event in the file.

Click back into the earth.txt file, and add a second line:

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.

Save the file (make sure to have a newline at the end!).

When we run git status now, it tells us that a file it already knows about has been modified:

BASH

$ git status

OUTPUT

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:   earth.txt

no changes added to commit (use "git add" and/or "git commit -a")

The last line is the key phrase: “no changes added to commit”. We have changed this file, but we haven’t told Git we will want to save those changes (which we do with git add) nor have we saved them (which we do with git commit). So let’s do that now. It is good practice to always review our changes before saving them. We do this using git diff. This shows us the differences between the current state of the file and the most recently saved version:

BASH

$ git diff

OUTPUT

diff --git a/earth.txt b/earth.txt
index 0b592c6..d27fc77 100644
--- a/earth.txt
+++ b/earth.txt
@@ -1 +1,2 @@
 Thor defends New Asgard from invaders.
+Thor and Valkyrie coordinate a counterattack.

The output is cryptic because it is actually a series of commands for tools like editors and patch telling them how to reconstruct one file given the other. If we break it down into pieces:

  1. The first line tells us that Git is producing output similar to the Unix diff command comparing the old and new versions of the file.
  2. The second line tells exactly which versions of the file Git is comparing; 0b592c6 and d27fc77 are unique computer-generated labels for those versions.
  3. The third and fourth lines once again show the name of the file being changed.
  4. The remaining lines are the most interesting, they show us the actual differences and the lines on which they occur. In particular, the + marker in the first column shows where we added a line.

After reviewing our change, it’s time to commit it:

BASH

$ git commit -m "Implement counterattack strategy"

OUTPUT

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:   earth.txt

no changes added to commit (use "git add" and/or "git commit -a")

Whoops: Git won’t commit because we didn’t use git add first. Let’s fix that:

BASH

$ git add earth.txt
$ git commit -m "Implement counterattack strategy"

OUTPUT

[main ee67c8b] Implement counterattack strategy
 1 file changed, 1 insertion(+)

Git insists that we add files to the set we want to commit before actually committing anything. This allows us to commit our changes in stages and capture changes in logical portions rather than only large batches.

To allow for this, Git has a special staging area where it keeps track of things that have been added to the current changeset but not yet committed.

Callout

If you think of Git as taking snapshots of changes over the life of a project, git add specifies what will go in a snapshot (putting things in the staging area), and git commit then actually takes the snapshot, and makes a permanent record of it (as a commit). If you don’t have anything staged when you type git commit, Git will prompt you to use git commit -a or git commit --all, which is kind of like gathering everyone for the picture! However, it’s almost always better to explicitly add things to the staging area, because you might commit changes you forgot you made. (Going back to snapshots, you might get the extra with incomplete makeup walking on the stage for the snapshot because you used -a!) Try to stage things manually, or you might find yourself searching for “git undo commit” more than you would like!

The Git Staging Area
The Git Staging Area

Using the Source Control pane in VS Code


Let’s watch as our changes to a file move from our editor to the staging area and into long-term storage. First, we’ll add another line to the file:

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.

Save the file (with a newline at the end!).

Switch from the Explorer pane view to the Source Control pane view in VS Code.

Under “Changes”, you should see your earth.txt file. Click the file.

In your Terminal window, type the command:

BASH

$ git diff

OUTPUT

diff --git a/earth.txt b/earth.txt
index d27fc77..8938f14 100644
--- a/earth.txt
+++ b/earth.txt
@@ -1,2 +1,3 @@
 Thor defends New Asgard from invaders.
 Thor and Valkyrie coordinate a counterattack.
+Thor reunites with Jane Foster at the sanctuary.

The git diff command is accomplishing the same thing as clicking on the file under “Changes”: that we’ve added one line to the end of the file (shown with a + in the first column).

In the Source Control pane, click the + icon next to the earth.txt file. The earth.txt file gets moved to the “Saved Changes” section.

Clicking the + icon accomplished the same thing as typing git add earth.txt in the terminal.

Now, let’s save our changes. We could use the Terminal to commit our changes:

BASH

$ git commit -m "Complete story with Thor-Jane reunion"

OUTPUT

[main 2f2d364] Complete story with Thor-Jane reunion
 1 file changed, 1 insertion(+)

Or, we can type the commit message “Complete story with Thor-Jane reunion” in the “Message” box and click “Commit”.

Let’s check our status:

BASH

$ git status

OUTPUT

On branch main
Your branch is ahead of 'origin/main' by 3 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

and look at the history of what we’ve done so far:

BASH

$ git log

OUTPUT

commit 2f2d364f559efb1101647591d9fbf2cc30ade8bb (HEAD -> main)
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 20:29:51 2025 -0400

    Complete story with Thor-Jane reunion

commit ee67c8b551612e09be46c97726866d04c7b0d785
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 20:24:35 2025 -0400

    Implement counterattack strategy

commit 9b26458f5d229d48be61023bcb510f8beb3f13db
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 20:18:55 2025 -0400

    Start story for New Asgard in earth.txt

commit f537d84c6ef9b6d988f642400b2017f855f9aaa1 (origin/main, origin/HEAD)
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 18:34:45 2025 -0400

    Initial commit

Challenge

Look back at the Source Control pane. Where can you see a GUI representation of this log?

Key Points

  • git status shows the status of a repository.
  • Files can be stored in a project’s working directory (which users see), the staging area (where the next commit is being built up) and the local repository (where commits are permanently recorded).
  • git add puts files in the staging area.
  • git commit saves the staged content as a new commit in the local repository.
  • Always write a log message when committing changes.

Content from Pushing changes to GitHub


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • How do I share my changes with others on the web?

Objectives

  • Push to or pull from a remote repository.

Local vs Remote Repositories


Version control really comes into its own when we begin to collaborate with other people. We already have most of the machinery we need to do this; the only thing missing is to copy changes from one repository to another.

Systems like Git allow us to move work between any two repositories. In practice, though, it’s easiest to use one copy as a central hub, and to keep it on the web rather than on someone’s laptop. Most programmers use hosting services like GitHub, Bitbucket or GitLab to hold those main copies; we’re using GitHub.

Before we share our changes, let’s first look at our multiverse repo on GitHub.

Even though we have made changes to our local copy of multiverse, the remote copy on GitHub still only has the README file. This is because we have not yet “pushed” our changes (or commits) to the remote repository.

Callout

Note that our local repository still contains our earlier work on earth.txt, but the remote repository on GitHub only contains the README file.

Because we created our repo on GitHub first and then cloned it to our local computer, the two repositories are already connected. If we had instead created the local repo first, then the remote repo on GitHub, we would need to manually connect the two repos, with a commmand like:

BASH

$ git remote add origin git@github.com:loki-god-of-stories/multiverse.git

origin is a local name used to refer to the remote repository. It could be called anything, but origin is a convention that is often used by default in git and GitHub, so it’s helpful to stick with this unless there’s a reason not to.

Instead, we can simply verify that the two repositories are connected with the command:

BASH

$ git remote -v

OUTPUT

origin  https://github.com/loki-god-of-stories/multiverse.git (fetch)
origin  https://github.com/loki-god-of-stories/multiverse.git (push)

Pushing local changes to GitHub


This command will push the changes from our local repository to the repository on GitHub:

BASH

$ git push origin main

OUTPUT

Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 992 bytes | 992.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/loki-god-of-stories/multiverse.git
   f537d84..2f2d364  main -> main

We can pull changes from the remote repository to the local one as well:

BASH

$ git pull origin main

OUTPUT

From https://github.com/loki-god-of-stories/multiverse
 * branch            main       -> FETCH_HEAD
Already up to date.

Pulling has no effect in this case because the two repositories are already synchronized. If someone else had pushed some changes to the repository on GitHub, though, this command would download them to our local repository.

Let’s verify that our changes made it to GitHub: go to your browser window with the GitHub repo and refresh the page.

Changes have been pushed
Changes have been pushed

You should now see the earth.txt file. Click on the file, and you can see the contents of the file are the same as in VS Code.

View earth.txt
View earth.txt

Now click on the “History” link. You should see each commit made to the file, even though we only pushed once.

View earth.txt commits
View earth.txt commits

Key Points

  • A local Git repository can be connected to one or more remote repositories.
  • git push copies changes from a local repository to a remote repository.
  • git pull copies changes from a remote repository to a local repository.

Content from Branches


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • What are branches?
  • How can I work in parallel using branches?

Objectives

  • Understand why branches are useful for:
  • working on separate tasks in the same repository concurrently
  • trying multiple solutions to a problem
  • check-pointing versions of code
  • Merge branches back into the main branch

So far we’ve always been working in a straight timeline. However, there are times when we might want to keep our main work safe from experimental changes we are working on. To do this we can use branches to work on separate tasks in parallel without changing our current branch, main.

We didn’t see it before but the first branch made is called main. This is the default branch created when initializing a repository and is often considered to be the “clean” or “working” version of a repository’s code.

We can see what branches exist in a repository by typing

BASH

$ git branch

OUTPUT

* main

The ’*’ indicates which branch we are currently on.

In this lesson, Loki needs to track two possible branching timelines, with two different versions of events happening on Asgard. Only one of these timeline branches will become part of the “main” timeline. In one timeline, Heimdall, guardian of the bifrost bridge, is aware of the invasion in New Asgard. In another timeline, Heimdall is blinded by powerful magic and is unaware of any trouble in New Asgard.

First let’s make the branch where Heimdall is aware. We use the same git branch command but now add the name we want to give our new branch

BASH

$ git branch heimdall-aware

We can now check our work with the git branch command.

BASH

$ git branch

OUTPUT

  heimdall-aware
* main

We can see that we created the heimdall-aware branch but we are still in the main branch.

We can also see this in the output of the git status command.

BASH

$ git status

OUTPUT

On branch main
nothing to commit, working directory clean

To switch to our new branch we can use the checkout command we learned earlier and check our work with git branch.

BASH

$ git checkout heimdall-aware
$ git branch

OUTPUT

* heimdall-aware
  main

Callout

We can use the checkout command to checkout a file from a specific commit using commit hashes or HEAD and the filename (git checkout HEAD <file>). The checkout command can also be used to checkout an entire previous version of the repository, updating all files in the repository to match the state of a desired commit.

Branches allow us to do this using a human-readable name rather than memorizing a commit hash. This name also typically gives purpose to the set of changes in that branch. When we use the command git checkout <branch_name>, we are using a nickname to checkout a version of the repository that matches the most recent commit in that branch (a.k.a. the HEAD of that branch).

Here you can use git log and ls to see that the history and files are the same as our main branch. This will be true until some changes are committed to our new branch.

BASH

$ git log --oneline

OUTPUT

2f2d364 (HEAD -> heimdall-aware, origin/main, origin/HEAD, main) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Now lets write what happens on Asgard.

Use the “New file” button to create a new file called asgard.txt.

Add one line to this file (and make sure to end with a newline), and then save it:

OUTPUT

Heimdall watches from afar, aware of New Asgard's plight.

Now we can add and commit the script to our branch.

BASH

$ git add asgard.txt
$ git commit -m "Create asgard.txt detailing Heimdall's awareness of invasion"

OUTPUT

[heimdall-aware daf95c3] Create asgard.txt detailing Heimdall's awareness of invasion
 1 file changed, 1 insertion(+)
 create mode 100644 asgard.txt

Lets check our work!

BASH

$ git log --oneline

OUTPUT

daf95c3 (HEAD -> heimdall-aware) Create asgard.txt detailing Heimdall's awareness of invasion
2f2d364 (origin/main, origin/HEAD, main) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

As expected, we see our commit in the log.

Now let’s switch back to the main branch.

BASH

$ git checkout main
$ git branch

OUTPUT

  heimdall-aware
* main

Let’s explore the repository a bit.

Now that we’ve confirmed we are on the main branch again. Let’s confirm that asgard.txt and our last commit aren’t in main.

BASH

$ git log --oneline

OUTPUT

2f2d364 (HEAD -> main, origin/main, origin/HEAD) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Callout

We no longer see the file asgard.txt and our latest commit doesn’t appear in this branch’s history. But do not fear! All of our hard work remains in the heimdall-aware branch. We can confirm this by moving back to that branch.

BASH

$ git checkout heimdall-aware
$ git branch

OUTPUT

* heimdall-aware
  main

BASH

$ git log --oneline

And we see that our asgard.txt file and respective commit have been preserved in the heimdall-aware branch.

Checkout the main branch again to prepare for creating another new branch based on the version history in main. New branches will include the entire history up to the current commit, and we’d like to keep these two tasks separate.

BASH

$ git checkout main
$ git branch

OUTPUT

  heimdall-aware
* main

Now we can keep track of a different timeline branching off from the main timeline.

This time let’s create and switch to the heimdall-blind branch in one command.

We can do so by adding the -b flag to checkout.

BASH

$ git checkout -b heimdall-blind
$ git branch

OUTPUT

  heimdall-aware
* heimdall-blind
  main

We can use git log to see that this branch is the same as our current main branch.

BASH

$ git log --oneline

OUTPUT

2f2d364 (HEAD -> heimdall-blind, origin/main, origin/HEAD, main) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Now we can a file for Asgard again and write the different version of events. This time, let’s make a markdown file instead of a text file.

Use the “New File” button to create a new file called asgard.md and add this line:

Heimdall's vision is blocked by *ancient magic*, unaware of New Asgard's danger.

BASH

$ git add asgard.md
$ git commit -m "Create asgard.md describing Heimdall's blocked vision"

OUTPUT

[heimdall-blind 59b9bab] Create asgard.md describing Heimdall's blocked vision
 1 file changed, 1 insertion(+)
 create mode 100644 asgard.md

Lets check our work again before we switch back to the main branch.

BASH

$ git log --oneline

OUTPUT

59b9bab (HEAD -> heimdall-blind) Create asgard.md describing Heimdall's blocked vision
2f2d364 (origin/main, origin/HEAD, main) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Loki decides the version of events where Heimdall is aware should be part of the main timeline.

We will merge the heimdall-aware branch into our main branch via a Pull Request so we can use it for our work going forward.

Before we can create a Pull Request on GitHub, we need to push this branch to the remote repo

Let’s checkout & push the heimdall-aware branch:

BASH

$ git checkout heimdall-aware
$ git push

Whoops, we got an error:

OUTPUT

fatal: The current branch heimdall-aware has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin heimdall-aware

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

While our main branch was already on both our local and remote repositories, our heimdall-aware branch is only on our local computer. You can check this by going to GitHub and searching for the heimdall-aware branch - you won’t find it!

We need to use the -u flag in our command and specify the destination branch.

BASH

$ git push -u origin heimdall-aware

OUTPUT

Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 406 bytes | 406.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'heimdall-aware' on GitHub by visiting:
remote:      https://github.com/loki-god-of-stories/multiverse/pull/new/heimdall-aware
remote:
To https://github.com/loki-god-of-stories/multiverse.git
 * [new branch]      heimdall-aware -> heimdall-aware
branch 'heimdall-aware' set up to track 'origin/heimdall-aware'.

The ‘-u’ Flag

You may see a -u option used with git push in some documentation. This option is synonymous with the --set-upstream-to option for the git branch command, and is used to associate the current branch with a remote branch so that the git pull command can be used without any arguments. To do this, simply use git push -u origin <branch-name>.

Now, we can go back to GitHub and verify that we have a new branch named heimdall-aware.

GitHub has the branch heimdall-aware
GitHub has the branch heimdall-aware

Key Points

  • Branches can be useful for developing while keeping the main line static.

Content from Pull Requests


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • What are pull requests for?
  • How can I make a pull request?

Objectives

  • Define the terms fork, clone, origin, remote, upstream
  • Understand how to make a pull request and what they are useful for

Callout

Pull requests are a great way to collaborate with others using github. Instead of making changes directly to a repository you can suggest changes to a repo. This can be useful if you don’t have permission to modify a repository directly or you want someone else to review your changes.

On GitHub, in your multiverse repo, click on the “Pull Requests” tab.

Then click “New pull request”. Alternatively, GitHub will see your new branch with recent changes and will prompt you to “Compare & pull request”. Click this button to also be taken to the new pull request page.

Open a Pull Request on GitHub for branch heimdall-aware
Open a Pull Request on GitHub for branch heimdall-aware

Make sure that the “base” branch is main and the “compare” branch is heimdall-aware.

Next, we need to give our PR a title. By default, your PR will get the title from your last commit. We can leave this as is.

Click “Create pull request”.

Pull Request is created
Pull Request is created

Your multiverse repo should now have 1 pull request. This is the phase where you would normally request a reviewer, who can leave comments on your code. In repos that you do not own, your PR will need to be approved by a codeowner before you can merge it. Since you are the codeowner, we can go ahead and click “Merge pull request”. Confirm & complete the merge.

Go back to the “Code” tab and make sure you are on the “main” branch. You should now see an “asgard.txt” file.

Let’s go back to VS Code. Checkout the main branch, and look at the files and history:

BASH

$ git checkout main
$ git log --oneline

OUTPUT

2f2d364 (HEAD -> main, origin/main, origin/HEAD) Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

The analysis file is not on “main” yet. This is because we need to first pull the changes we made with the Pull Request from the remote repository.

BASH

$ git pull

OUTPUT

remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (1/1), 952 bytes | 476.00 KiB/s, done.
From https://github.com/loki-god-of-stories/multiverse
   2f2d364..976b48e  main       -> origin/main
Updating 2f2d364..976b48e
Fast-forward
 asgard.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 asgard.txt
$ git log --oneline

OUTPUT

976b48e (HEAD -> main, origin/main, origin/HEAD) Merge pull request #1 from loki-god-of-stories/heimdall-aware
daf95c3 (origin/heimdall-aware, heimdall-aware) Create asgard.txt detailing Heimdall's awareness of invasion
2f2d364 Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Now our main branch is up to date.

Deleting branches


Now that we’ve merged the heimdall-aware into main, these changes exist in both branches. This could be confusing in the future if we stumble upon the heimdall-aware branch again.

We can delete our old branches so as to avoid this confusion later. We can do so by adding the -d flag to the git branch command.

BASH

git branch -d heimdall-aware

OUTPUT

Deleted branch heimdall-aware (was daf95c3).

And because we don’t want to keep the changes in the heimdall-blind branch, we can delete the heimdall-blind branch as well

BASH

$ git branch -d heimdall-blind

OUTPUT

error: The branch 'heimdall-blind' is not fully merged.
If you are sure you want to delete it, run 'git branch -D heimdall-blind'.

Since we’ve never merged the changes from the heimdall-blind branch, git warns us about deleting them and tells us to use the -D flag instead.

Since we really want to delete this branch we will go ahead and do so.

BASH

git branch -D heimdall-blind

OUTPUT

Deleted branch heimdall-blind (was 59b9bab).

Finally, we can also delete the heimdall-aware branch on GitHub. Click on “Branches”, and to delete the heimdall-aware branch click the trashcan icon to the right of the branch name.

Key Points

  • Pull requests suggest changes to repos where you don’t have privileges

Content from [Optional] Resolving Conflicts


Last updated on 2025-05-23 | Edit this page

Overview

Questions

  • What do I do when my changes conflict?

Objectives

  • Explain what conflicts are and when they can occur.
  • Understand how to resolve conflicts resulting from a merge.

As soon as people can work in parallel, they’ll likely step on each other’s toes. This will even happen with a single person: if we are working on a piece of software on two different computers, we could make different changes to each copy. Version control helps us manage these conflicts by giving us tools to resolve overlapping changes.

To see how we can resolve conflicts, we must first create one. The file earth.txt currently looks like this in our multiverse repository:

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.

Let’s create a new branch to describe 1 possible version of events to occur next.

BASH

$ git branch loki-twist

But before we checkout the loki-twist branch and add the event where Loki enters the picture, let’s add a line to earth.txt here in the main branch.

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.
The invaders retreat as Heimdall's rainbow bridge returns.

and commit that change to the main branch

BASH

$ git add earth.txt
$ git commit -m "Add invaders retreat"

OUTPUT

[main a521b20] Add invaders retreat
 1 file changed, 1 insertion(+)

We can then examine the commit history of the main branch.

BASH

$ git log --oneline

OUTPUT

a521b20 (HEAD -> main) Add invaders retreat
976b48e (origin/main, origin/HEAD) Merge pull request #1 from loki-god-of-stories/heimdall-aware
daf95c3 (origin/heimdall-aware) Create asgard.txt detailing Heimdall's awareness of invasion
2f2d364 Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Now that we’ve made our changes in the main branch, let’s add an event to the loki-twist branch.

BASH

$ git checkout loki-twist
$ git branch

OUTPUT

* loki-twist
  main

Let’s add a line in earth.txt with Loki’s reveal. Note that when we open this file the line we added about the invaders retreating will not be present as that change is not part of this branch.

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.
Loki appears, revealing the invasion was his test all along.

Now let’s commit this change to the loki-twist branch

BASH

$ git add earth.txt
$ git commit -m "Add twist ending with Loki as mastermind"

OUTPUT

[loki-twist 7b972b4] Add twist ending with Loki as mastermind
 1 file changed, 1 insertion(+)

Again, we can look at the history of this branch.

BASH

$ git log --oneline

OUTPUT

7b972b4 (HEAD -> loki-twist) Add twist ending with Loki as mastermind
976b48e (origin/main, origin/HEAD) Merge pull request #1 from loki-god-of-stories/heimdall-aware
daf95c3 (origin/heimdall-aware) Create asgard.txt detailing Heimdall's awareness of invasion
2f2d364 Complete story with Thor-Jane reunion
ee67c8b Implement counterattack strategy
9b26458 Start story for New Asgard in earth.txt
f537d84 Initial commit

Callout

Notice that the commit related to the invaders retreating is not present as it is part of the main branch, not the loki-twist branch.

Now that we’ve added Loki’s big reveal, we can merge this branch into the main branch. We’re going to do this merge in VS Code rather than through a Pull Request in GitHub this time.

First, let’s checkout the main branch.

BASH

$ git checkout main
$ git branch

OUTPUT

  loki-twist
* main

And then merge the changes from loki-twist into our current branch, main.

BASH

$ git merge loki-twist

OUTPUT

Auto-merging earth.txt
CONFLICT (content): Merge conflict in earth.txt
Automatic merge failed; fix conflicts and then commit the result.

Review the status of the repository now that we’ve been told merging has resulted in a conflict.

BASH

$ git status

OUTPUT

On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   earth.txt

no changes added to commit (use "git add" and/or "git commit -a")
The Conflicting Changes
The Conflicting Changes

Git detects that the changes made in one copy overlap with those made in the other and stops us from trampling on our previous work. It also marks that conflict in the affected file, earth.txt.

Merge conflict in earth.txt
Merge conflict in earth.txt

Our change — the one at the HEAD of the main branch — is preceded by <<<<<<<. Git has then inserted ======= as a separator between the conflicting changes and marked the end of our commit from the loki-twist branch with >>>>>>>. (The string of letters and digits after that marker identifies the commit we made in the loki-twist branch.)

It is now up to us to edit this file and reconcile the changes. We can do anything we want: keep the change made in the main branch, keep the change made in the loki-twist branch, write something new to replace both, or get rid of the change entirely.

Let’s keep both of these events, but save Loki’s reveal for after the invaders reatreat.

VS Code will prompt you to “Resolve in Merge Editor”. Click this button.

Resolving the merge conflict with the merge editor
Resolving the merge conflict with the merge editor

In the Merge Editor, you will see the two versions side by side, and the final version of the file below. We want the final version to look like:

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.
The invaders retreat as Heimdall's rainbow bridge returns.
Loki appears, revealing the invasion was his test all along.

So we want to click “Accept Combination (Current First)”. You should now see the resolved version with both lines, the line from the main branch first. Click “Complete Merge”.

The bottom pane contains the resolved earth.txt contents
The bottom pane contains the resolved earth.txt contents

By clicking “Complete Merge”, you are doing the same thing as running the command git add earth.txt. If you open the Source Control pane, you should see earth.txt under “Staged Changes”. You can then complete the commit using the VS Code UI or on the command line

BASH

$ git commit -m "Merge changes from loki-twist"

OUTPUT

[main c5c81b3] Merge changes from loki-twist

Take a look at the Source Control Graph window (in the lower portion of the Source Control pane) for a visual representation of the git log.

$ git log

OUTPUT

commit c5c81b35d7631b4aa9c7d71d06253c593cbaf644 (HEAD -> main)
Merge: a521b20 7b972b4
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 21:36:55 2025 -0400

    Merge branch 'loki-twist'

commit 7b972b4d86972ddfbacac225c5c84c8b4a5609ff (loki-twist)
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 21:27:20 2025 -0400

    Add twist ending with Loki as mastermind

commit a521b20ef97343b49b3b25717e485b360fcb8d64
Author: Loki Odinson <loki.odinson@tva.org>
Date:   Sat May 17 21:25:13 2025 -0400

    Add invaders retreat

When conflicts resolve themselves


Let’s make another change to the loki-twist branch:

$ git checkout loki-twist

Add another line to earth.txt:

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.
Loki appears, revealing the invasion was his test all along.
Thor smiles, having known his brother's scheme from the beginning.

BASH

$ git add earth.txt
$ git commit -m "Add Thor's knowing reaction to Loki's scheme"

OUTPUT

[loki-twist 959f09c] Add Thor's knowing reaction to Loki's scheme
 1 file changed, 1 insertion(+)

And merge that change into main branch

BASH

$ git checkout main
$ git merge loki-twist

OUTPUT

Updating c5c81b3..959f09c
Fast-forward
 earth.txt | 1 +
 1 file changed, 1 insertions(+), 0 deletions(-)

Git keeps track of what we’ve merged with what, so we don’t have to fix things by hand again. There is no conflict and our changes are added automatically.

Finally, let’s update our remote repository:

BASH

$ git push

Still seeing a conflict?

This exercise is dependent on how the merge conflict was resolved in our first merge of the loki-twist branch and may still result in a conflict when merging additional commits from the loki-twist branch.

OUTPUT

Thor defends New Asgard from invaders.
Thor and Valkyrie coordinate a counterattack.
Thor reunites with Jane Foster at the sanctuary.
The invaders retreat as Heimdall's rainbow bridge returns.
Loki appears, revealing the invasion was his test all along.
Thor smiles, having known his brother's scheme from the beginning.

We don’t need to merge again because Git knows someone has already done that.

Git’s ability to resolve conflicts is very useful, but conflict resolution costs time and effort, and can introduce errors if conflicts are not resolved correctly. If you find yourself resolving a lot of conflicts in a project, consider these technical approaches to reducing them:

  • Pull from upstream more frequently, especially before starting new work
  • Use topic branches to separate work, merging to main when complete
  • Make smaller more atomic commits
  • Where logically appropriate, break large files into smaller ones so that it is less likely that two authors will alter the same file simultaneously

Conflicts can also be minimized with project management strategies:

  • Try breaking large files apart into smaller files so that it is less likely that you will be working in the same file at the same time in different branches
  • Create branches focused on separable tasks so that your work won’t overlap in files
  • Clarify who is responsible for what areas with your collaborators
  • Discuss what order tasks should be carried out in with your collaborators so that tasks that will change the same file won’t be worked on at the same time

Practice resolving conflicts with a partner

You can repeat this exercise twice, once in your multiverse repo, and once in your partner’s.

You will first need to clone your partner’s multiverse repo in order to make edits in it.

You will each create a new branch in the same multiverse repo, and make a small conflicting change (e.g. adding two different lines to the end of earth.txt).

The repo owner should then create a Pull Request and merge their branch first.

The other person should then create a Pull Request to merge their branch. They will get a merge conflict.

In VS Code, they can merge main into their branch and resolve the conflict, then push the commit with the resolved merge to GitHub. They should now be able to merge their branch into main as well.

Key Points

  • Conflicts occur when files are changed in the same place in two commits that are being merged.
  • The version control system does not allow one to overwrite changes blindly during a merge, but highlights conflicts so that they can be resolved.

Content from [Optional] Practice GitHub Skills


Last updated on 2025-04-07 | Edit this page

Overview

Questions

  • How can I practice these git skills?

Objectives

  • Complete GitHub Skills courses for further practice

The following GitHub Skills courses are recommended for further independent practice:

Follow the directions in the README files for each of the courses. Each course is a repo that you will fork, creating a copy of the repo under your username. The course progresses using GitHub Actions, which means you must follow the directions exactly.

Key Points

  • You can review these concepts by completing some recommended GitHub Skills courses