Gitting Started: git in ECE 3700

What git is for

git is a revision control system that is heavily used in software and computer engineering. It keeps track of file changes, allows sharing among multiple developers, and handles merges when changes are made by multiple people simultaneously.

In ECE 3700 we will use git to coordinate digital design assignments between students and the instructor. The instructor will have a synchronized copy of each student’s files, so that the instructor can efficiently track student progress and provide assistance with the assigned tasks.

The instructor will maintain a central git repository containing all the assignments for the semester. Each student is provided with a fork repository that is initially a copy of the instructor’s version. When a student works on an assignment, they commit and push their files onto the server. The instructor will regularly pull students’ changes to stay synchronized.

In this assignment, students will:

Assigned Tasks

Use a Terminal Emulator

The first thing you need is a terminal emulator capable of running git and ssh. Setup instructions are provided in a separate document. Make sure you are comfortable using the terminal before continuing with this assignment. Practice basic tasks like directory listings with ls, changing directories with cd, creating directories with mkdir, and so on.

Test the git command by running

git --version

You should see a version number. If you instead see a “command not found” or similar message, then something is wrong with your setup.

Clone your Repository

You should receive personal account credentials include a username and password that can be used both for remote server access and for git access. To download a copy of your gitting_started repository, follow this procedure:

  1. On your computer, create a directory to contain git repositories. I call mine ~/gitclones and created it with the command
    mkdir ~/gitclones

  2. Change into your gitclones directory using
    cd ~/gitclones

  3. Now download your clone using the git clone command:

   git clone https://username:passwd@left.engr.usu.edu/git/username/gitting_started

In this command you should replace username with your actual username, and replace password with your actual password. So if your username is dill and your password is pickle, you would type:

   git clone https://dill:pickle@left.engr.usu.edu/git/dill/gitting_started
  1. Navigate to your clone:
    cd gitting_started
    In the future you can access this clone in your terminal by typing
    cd ~/gitclones/gitting_started

Identify Yourself

Before making edits, you need to configure your Real Name and Email Address. This is so that when you share your edits on the server, other users (i.e. the instructor) can easily see who you are. To edit your identity, type the following line in the terminal and press Enter:

git config --global --edit

This will bring up a terminal-based text editor with the identity configuration file. By default, the text editor is vim. At first, vim opens in read-only mode. To make edits, you need to press i. When finished with edits, you press ESC. To save the file and exit, you type the command sequence :x (two keypresses, then Enter).

An example configuration is shown below. Make edits to set your identity, then save and exit.

# This is Git's per-user configuration file.
[user]
# Please adapt and uncomment the following lines:
name = Dill Pickle
email = dillpickle@aggiemail.usu.edu

Summary of some vim editing commands:

i | “insert” | start editing |
ESC | “cancel” | stop editing |
u | “undo” | undo last edit (need to ESC first) |
:w | “write” | save the file |
:x | “save/exit” | save and quit |
:q | “quit” | quit without save |

Many power users like to use vim. I don’t. Many like myself prefer to use emacs, others may prefer a GUI editor like Notepad. You can change the default editor by running this command:

git config --global core.editor "<command name>"

So for me, I would use the command name "emacs". After changing your editor, test the change by repeating the git config --global --edit command, to make sure you did it right.

Edit a File

In your cloned repository, do a directory listing using ls. You should see a file called file.txt. Open the file with a text editor, make some changes, and then save the file. In your terminal, type

git status .

The command output will look like this, indicating that file.txt has been modified:

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 checkout -- <file>..." to discard changes in working directory)

    modified:   file.txt

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

Add a File

Next, using the terminal, create a new text file using the cat command:

cat > newfile.txt

Type some words. When finished, press Enter for a new line, then type Ctrl-D to close the file.

Next, type

git status .

You should see output 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 checkout -- <file>..." to discard changes in working directory)

    modified:   file.txt

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

    newfile.txt

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

The status message reports that newfile.txt is untracked, meaning that it is not part of the repository, it’s history is not recorded and it is not shared with the server.

To include this file in your repository, use the git add command:

git add newfile.txt

Then run a git status . check again and you should see:

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

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   newfile.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   file.txt

This indicates that git is aware of newfile.txt and will include it in repository actions from now on.

Commit Changes

After making changes and adding files, the changes are not yet confirmed. To make them official, you need to commit them to the repository:

git commit . -m "Type a brief message describing what was changed."

You can review the commit by running

git log --name-status HEAD^..HEAD

It should show an output like this:

Author: Dill Pickle <dillpickle@aggiemail.usu.edu>
Date:   Wed Dec 23 10:26:02 2020 -0700

    Made a new file, edited an old file.

M       file.txt
A       newfile.txt

Push Changes

After committing changes, the commit still needs to be shared with the server and other users (i.e. the instructor). To do this, you push your commit to the server:

git push origin main

It will printout a technical message tallying all the changes sent to the server. The last few lines should look something like this:

Writing objects: 100% (6/6), 2.60 KiB | 2.60 MiB/s, done.
Total 6 (delta 3), reused 0 (delta 0), pack-reused 0
To https://left.engr.usu.edu/git/dillpickle/gitting_started
   945d1e8..873f856  main -> main

The two random-looking strings are version hash strings, which serve as unique identifiers for every commit. The push output only shows the first seven characters of the hash, but is enough to identify the revisions in your own commit history.

View the history by running git log in the terminal. The top entry should look like this:

commit 873f856b806a00a515a54f71a65ff833cd56201c (HEAD -> main, origin/main)
Author: Dill Pickle <dillpickle@aggiemail.usu.edu>
Date:   Wed Dec 23 10:26:02 2020 -0700

    Made a new file, edited an old file.

After the word commit you should notice the string 873f856. This matches the hash code reported for your most recent push. The line also indicates -> main, origin/main, which informs you that this commit was pushed to the server.

Pull Changes

For this tutorial, when you make a commit the server will respond by appending an automated message to newfile.txt. This simulates a remote edit made by the instructor or another user. To see if there are new changes on the server, run

git remote show origin

This command will list some basic details about the server repository. You just need to look at the last line:

   main pushes to main (local out of date)

The key phrase here is local out of date. This means there is new data on the server. To download it, run

git pull origin main

The output will look something like this:

remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), 296 bytes | 296.00 KiB/s, done.
From https://left.engr.usu.edu/git/dillpickle/gitting_started
 * branch            main     -> FETCH_HEAD
   873f856..9d45e00  main     -> origin/main
Updating 873f856..9d45e00
Fast-forward
 newfile.txt | 2 ++
 1 file changed, 2 insertions(+)

The last few lines indicate which files are changed.

Review Remote Changes

After pulling changes from the server, you can see exactly what was changed using the git diff command:

git diff HEAD^ HEAD

This runs a diff command to compare your most recent version (HEAD^) against the current version (HEAD). The output will look something like this:

diff --git a/newfile.txt b/newfile.txt
index 9472d00..a10b0c8 100644
--- a/newfile.txt
+++ b/newfile.txt
@@ -1 +1,3 @@
 here is new file.
+
+I see you. You are seen.

The @@ symbols indicate the location of the edit: @@ -1 indicates the first line of file1 (from the HEAD^ commit), and +1,3 @@ indicates the first line of file2 (from the HEAD commit), continuing for three lines. Lines beginning with + are newly added in the latest revision.

Fetch and Merge

From time to time, the instructor will deploy new material or corrections in the upstream repository. To merge these updates, you need to run git fetch and git merge:

git fetch upstream
git checkout main
git merge upstream/main

This will download any new material and merge it into your local repository.

Revert a File

Open file.txt and make some random edits. Now suppose you regret making those edits and want to revert back to the last commit. The quickest way is to use git restore:

git restore file.txt

Now view the contents of file.txt using the command cat file.txt, and you should see it has returned to its original condition.

If you find that you’ve made a complete mess in your local repository, you can restore everything by running

git restore

Now suppose you made a commit with bad changes. You can reset your repository to an earlier version using the hash code. Let’s simulate this process.

  1. Make some random edits to file.txt.
  2. Commit the edits using git commit file.txt -m "made random edits"
  3. Push the commit using git push origin main
  4. Review the history using git log file.txt

The log output will look something like this:

commit 68844b7449c41876bd0ed70705f060b27f449c02 (HEAD -> main, origin/main)
Author: Chris Winstead <chris.winstead@usu.edu>
Date:   Wed Dec 23 11:30:31 2020 -0700

    random edits to file.txt

commit 873f856b806a00a515a54f71a65ff833cd56201c
Author: Chris Winstead <winstead@trusty.hopto.org>
Date:   Wed Dec 23 10:26:02 2020 -0700

    Made a new file, edited an old file.

The top commit is the one we just did, with the random edits. But we regret this and wish we could go back to the way things were. We can rollback the file using git checkout like this

git checkout 873f856b file.txt

This replaces your version of the file with the one from 873f856b… (you don’t need the entire hash code to identify the version).

To rollback the entire project, you can stash your edits and run git revert like this:

git stash
git revert 873f856b

Resolving a merge conflict: At this point, it’s possible that file.txt had edits in both HEAD and 873f856, and git doesn’t want to make important decisions for you. Run git status in the terminal to reveal any merge conflicts. The output may look like this:

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
    both modified:   file.txt

This indicates that file.txt has ambiguous edits. Open file.txt in a text editor, and you will see this:

This is a file. Congratulations.
<<<<<<< HEAD


argle bargle

=======
>>>>>>> parent of 873f856... Made a new file, edited an old file.

In this file, git indicates the version differences between the <<<<<< and >>>>> lines. You need to decide what to keep and what to delete. Edit the file as you like, and when you are finished use git add to resolve the merge conflict:

git add file.txt
git commit . -m "Got file.txt back how I like it."