1. Solo work with git#

Getting started#

So, we’re in our git working directory:

import os

try:
    from google.colab import drive  # type: ignore

    drive.mount("/content/drive")
    drive_dir = "/content/drive/MyDrive"
except ImportError:
    print("Not running on colab")
    drive_dir = os.path.join(os.getcwd(), "drive", "MyDrive")
    os.makedirs(drive_dir, exist_ok=True)

print(f"Drive dir: {drive_dir}")

git_dir = os.path.join(drive_dir, "learning_git")
working_dir = os.path.join(git_dir, "git_example")

if os.path.exists(working_dir):
    print(f"Git example directory: {working_dir}")
    os.chdir(working_dir)
else:
    print("Start from the beginning")
Not running on colab
Drive dir: /mnt/nvme1n1p2/home/yj.lee/workspace/projects/lecture/book/lectures/softeng/vcs/drive/MyDrive
Start from the beginning

A first example file#

So let’s create an example file, and see how to start to manage a history of changes to it.

<my editor> test.md # Type some content into the file.
%%writefile test.md
Mountains in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.
Writing test.md
!cat test.md
Mountains in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.

Telling Git about the File#

So, let’s tell Git that test.md is a file which is important, and we would like to keep track of its history:

%%bash
git add test.md

Don’t forget: Any files in repositories which you want to “track” need to be added with git add after you create them.

Our first commit#

Now, we need to tell Git to record the first version of this file in the history of changes:

%%bash
git commit -m "First commit of discourse on UK topography"
[main (root-commit) 74efc42] First commit of discourse on UK topography
 1 file changed, 4 insertions(+)
 create mode 100644 test.md

And note the confirmation from Git.

There’s a lot of output there you can ignore for now.

Configuring Git with your editor#

If you don’t type in the log message directly with -m “Some message”, then an editor will pop up, to allow you to edit your message on the fly.

For this to work, you have to tell git where to find your editor.

git config --global core.editor vim

You can find out what you currently have with:

git config --get core.editor

To configure Notepad++ on Windows you’ll need something like the below:

git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -nosession -noPlugin"

You can use whatever editor you prefer. (Windows users could use Notepad++, Mac users could use textmate or Sublime Text, Linux users could use vim, nano or emacs.)

Commit logs#

Git log#

Git now has one change in its history:

%%bash
git log
commit 74efc42f190870df59f42e1013c8bcb766d119b9
Author: Young Joon Lee <entelecheia@hotmail.com>
Date:   Sun Sep 17 19:26:26 2023 +0900

    First commit of discourse on UK topography

You can see the commit message, author, and date…

Hash Codes#

The commit “hash code”, e.g.

74efc42f190870df59f42e1013c8bcb766d119b9

is a unique identifier of that particular revision.

This is a really long code, but whenever you need to use it, you can just use the first few characters. You just need however many characters is long enough to make it unique, for example 74efc42f1.

Nothing to see here#

Note that git will now tell us that our “working directory” is up-to-date with the repository: there are no changes to the files that aren’t recorded in the repository history:

%%bash
git status
On branch main
nothing to commit, working tree clean

Staging changes#

Let’s edit the file again:

vim test.md
%%writefile test.md
Mountains in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.

Mount Fictional, in Barsetshire, U.K. is the tallest mountain in the world.
Overwriting test.md
!cat test.md
Mountains in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.

Mount Fictional, in Barsetshire, U.K. is the tallest mountain in the world.

Unstaged changes#

%%bash
git status
On branch 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.md

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

We can now see that there is a change to “test.md” which is currently “not staged for commit”. What does this mean?

If we do a git commit now nothing will happen.

Git will only commit changes to files that you choose to include in each commit.

This is a difference from other version control systems, where committing will affect all changed files.

We can see the differences in the file with:

%%bash
git diff
diff --git a/test.md b/test.md
index 1852ebc..b63f764 100644
--- a/test.md
+++ b/test.md
@@ -2,3 +2,5 @@ Mountains in the UK
 ===================
 England is not very mountainous.
 But has some tall hills, and maybe a mountain or two depending on your definition.
+
+Mount Fictional, in Barsetshire, U.K. is the tallest mountain in the world.

Deleted lines are prefixed with a minus, added lines prefixed with a plus.

Staging a file to be included in the next commit#

To include the file in the next commit, we have a few choices. This is one of the things to be careful of with git: there are lots of ways to do similar things, and it can be hard to keep track of them all.

%%bash
git add --update

This says “include in the next commit, all files which have ever been included before”.

Note that git add is the command we use to introduce git to a new file, but also the command we use to “stage” a file to be included in the next commit.

The staging area#

The “staging area” or “index” is the git jargon for the place which contains the list of changes which will be included in the next commit.

You can include specific changes to specific files with git add, commit them, add some more files, and commit them. (You can even add specific changes within a file to be included in the index.)

The Levels of Git#

sequenceDiagram participant WD as Working Directory participant SA as Staging Area participant LR as Local Repository Note over WD: git add WD->>SA: Stage changes Note over SA: git commit SA->>LR: Commit staged changes Note over WD: git commit -a WD->>LR: Stage and commit changes

Correcting mistakes#

Review of status#

%%bash
git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   test.md
%%bash
git commit -m "Add a lie about a mountain"
[main 453f5bc] Add a lie about a mountain
 1 file changed, 2 insertions(+)
%%bash
git log
commit 453f5bcf1cfe7616ded061ca2b1cf1e910351824
Author: Young Joon Lee <entelecheia@hotmail.com>
Date:   Sun Sep 17 19:53:45 2023 +0900

    Add a lie about a mountain

commit 74efc42f190870df59f42e1013c8bcb766d119b9
Author: Young Joon Lee <entelecheia@hotmail.com>
Date:   Sun Sep 17 19:26:26 2023 +0900

    First commit of discourse on UK topography

Great, we now have a file which contains a mistake.

Carry on regardless#

In a while, we’ll use Git to roll back to the last correct version: this is one of the main reasons we wanted to use version control, after all! But for now, let’s do just as we would if we were writing code, not notice our mistake and keep working…

vim test.md
%%writefile test.md
Mountains and Hills in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.

Mount Fictional, in Barsetshire, U.K. is the tallest mountain in the world.
Overwriting test.md
!cat test.md
Mountains and Hills in the UK
===================
England is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.

Mount Fictional, in Barsetshire, U.K. is the tallest mountain in the world.

Commit with a built-in-add#

%%bash
git commit -am "Change title"
[main 6626d56] Change title
 1 file changed, 1 insertion(+), 1 deletion(-)

This last command, git commit -a automatically adds changes to all tracked files to the staging area, as part of the commit command. So, if you never want to just add changes to some tracked files but not others, you can just use this and forget about the staging area!

Review of changes#

%%bash
git log | head
commit 6626d56233bdf14ea2f9741588523c2a6d5c483d
Author: Young Joon Lee <entelecheia@hotmail.com>
Date:   Sun Sep 17 19:54:06 2023 +0900

    Change title

commit 453f5bcf1cfe7616ded061ca2b1cf1e910351824
Author: Young Joon Lee <entelecheia@hotmail.com>
Date:   Sun Sep 17 19:53:45 2023 +0900

We now have three changes in the history:

%%bash
git log --oneline
6626d56 Change title
453f5bc Add a lie about a mountain
74efc42 First commit of discourse on UK topography

Git Solo Workflow#

We can make a diagram that summarises the above story:

sequenceDiagram participant J as Jim participant I as Jim's index participant R as Jim's repo Note over J: vim test.md Note over J: git init J->>R: Create repository Note over J: git add test.md J->>I: Add content of test.md Note over J: git commit I->>R: Commit content of test.md Note over J: vim test.md Note over J: git add --update J->>I: Update content of test.md Note over J: git commit -m "Add a lie" I->>R: Commit change to test.md Note over J: vim test.md Note over J: git commit -am "Change title" J->>R: Add and commit change to test.md (and all tracked files)