Working inside a repository

The setup script is located in the git.zip file in the exercsises folder. Run ./working.sh for setup!

Introduction

In this exercise we will perform some basic task, like committing, partially staging and also some reset.

First we run git status --short or will use the provided alias for this git st and compare it to git status.

$ git status --short

 M partially_stage.txt
?? commit_me.txt
?? do_not_stage.txt
?? stage_me.txt

compare this to git status

$ 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:   partially_stage.txt

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

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

it is quite a bit shorter.

The first column in the short status indicates the index (stage), the second the working tree (working directory).

$ git log --oneline

b460609 (HEAD -> main) initial commit

shows one commit present already.

Stage and commit a file with a full commit message

The first task is to stage and commit the commit_me.txt file. And add the following commit message:

add commit_me.txt

Added the file because I was asked to.

Questions

After you completed the task:

Walkthrough

$ git add commit_me.txt
$ git status --short

A  commit_me.txt
 M partially_stage.txt
?? do_not_stage.txt
?? stage_me.txt

We now see, commit_me.txt is added to the index (staged).

git commit

The editor of your choice opens. You can change the default editor using git config --global core.editor XXXX.

Inside this editor add this commit message

add commit_me.txt

Added the file because I was asked to.

save and exit the editor. Now, answer the questions.

Partially staging a file

Stage the file stage_me.txt and partially stage the file partially_stage.txt then commit.

The only changes from partially_stage.txt to be committed must be do stage this line. In the end it should look like

do stage this line

Hint

There are two ways to do this. Either use git add -p filename to partially stage a file or use git add -i to be fully interactive and select the patch option when you have to.

Walkthrough

$ git add -i
           staged     unstaged path
  1:    unchanged        +3/-1 partially_stage.txt

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch   6: diff   7: quit   8: help
What now> a
           staged     unstaged path
  1: do_not_stage.txt
  2: stage_me.txt
Add untracked>> s
           staged     unstaged path
  1: do_not_stage.txt
* 2: stage_me.txt
# press enter again to exit adding
Add untracked>>
added 1 path

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch   6: diff   7: quit   8: help
What now> s
           staged     unstaged path
  1:    unchanged        +3/-1 partially_stage.txt
  2:        +1/-0      nothing stage_me.txt
What now>p
          staged     unstaged path
  1:    unchanged        +3/-1 partially_stage.txt
Patch update>> 1
           staged     unstaged path
* 1:    unchanged        +3/-1 partially_stage.txt
# press enter to start patching
Patch update>>
diff --git a/partially_stage.txt b/partially_stage.txt
index b9d3530..a31e092 100644
--- a/partially_stage.txt
+++ b/partially_stage.txt
@@ -1 +1,3 @@
-already tracked
+do not stage this line
+do stage this line
+but not this
(1/1) Stage this hunk [y,n,q,a,d,e,p,?]? ?
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
e - manually edit the current hunk
p - print the current hunk, 'P' to use the pager
? - print help
# we do not want to commit the whole hunk, so we edit it
(1/1) Stage this hunk [y,n,q,a,d,e,p,?]? e
# inside your editor edit the file to look like

@@ -1 +1,3 @@
-already tracked
+do stage this line

# save and exit

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch   6: diff   7: quit   8: help
What now> q

Now we should see a staged file stage_me.txt and a staged and modified file partially_stage.txt.

$ git status --short

MM partially_stage.txt
A  stage_me.txt
?? do_not_stage.txt

But what will be committed?

$ git diff --staged


diff --git a/partially_stage.txt b/partially_stage.txt
index b9d3530..2c938aa 100644
--- a/partially_stage.txt
+++ b/partially_stage.txt
@@ -1 +1 @@
-already tracked
+do stage this line
diff --git a/stage_me.txt b/stage_me.txt
new file mode 100644
index 0000000..63bda91
--- /dev/null
+++ b/stage_me.txt
@@ -0,0 +1 @@
+use complete file

Now commit with a message.

git commit -m "partially staged"

Amending a commit

Now, create an empty file forgotten.txt and add it to the last commit you make. What happens to the commit hash of this commit?

Walkthrough

$ git log --oneline

dec3fed (HEAD -> main) partially staged
0173e3b add commit_me.txt
e8886bd initial commit

$ touch forgotten.txt
$ git add forgotten.txt
$ git status --short

A  forgotten.txt
 M partially_stage.txt
?? do_not_stage.txt

$ git commit --amend
# the editor opens again, this time exit without changes

$ git log --oneline

3bfd8f7 (HEAD -> main) partially staged
0173e3b add commit_me.txt
e8886bd initial commit

The commit hash changed! We have a totally new commit.

Reflog

Run git reflog. What do you see? Can you spot the amend? Then run git log -g to print the reflog in a different style.

$ git reflog

3bfd8f7 (HEAD -> main) HEAD@{0}: commit (amend): partially staged
dec3fed HEAD@{1}: commit: partially staged
0173e3b HEAD@{2}: commit: add commit_me.txt
e8886bd HEAD@{3}: commit (initial): initial commit

$ git log -g

commit 3bfd8f73691e3645a184acdd9815fba2354c9e85 (HEAD -> main)
Reflog: HEAD@{0} (maschmi <maschmi@maschmi.net>)
Reflog message: commit (amend): partially staged
Author: maschmi <maschmi@maschmi.net>
Date:   Sun Jun 8 14:47:58 2025 +0200

    partially staged

commit dec3fed8ca4c8067bac9a726f9eb35132c6e7d74
Reflog: HEAD@{1} (maschmi <maschmi@maschmi.net>)
Reflog message: commit: partially staged
Author: maschmi <maschmi@maschmi.net>
Date:   Sun Jun 8 14:47:58 2025 +0200

    partially staged

commit 0173e3b0059ee5b8fd4657a3979f47ad1f8e8431
Reflog: HEAD@{2} (maschmi <maschmi@maschmi.net>)
Reflog message: commit: bla
Author: maschmi <maschmi@maschmi.net>
Date:   Sun Jun 8 14:34:10 2025 +0200

    add commit_me.txt

    Added the file because I was asked to.

commit e8886bd47b9636c24573b36d6ecde46538251482
Reflog: HEAD@{3} (maschmi <maschmi@maschmi.net>)
Reflog message: commit (initial): initial commit
Author: maschmi <maschmi@maschmi.net>
Date:   Sun Jun 8 14:34:00 2025 +0200

    initial commit

In both logs we can see the amend.

Detached Head

Git stores snapshots and not changes. Can you load such a snapshot? We will load the snapshot form our original commit with the message partially tagged.

Use reflog to find the original commit hash, check it out and then checkout main again.

Questions

Walkthrough

$ git checkout dec3fed

M partially_stage.txt
Note: switching to 'dec3fed'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at dec3fed partially staged

$ git checkout main

M partially_stage.txt
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  dec3fed partially staged

If you want to keep it by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> dec3fed

Switched to branch 'main'

$ git reflog

3bfd8f7 (HEAD -> main) HEAD@{0}: checkout: moving from dec3fed8ca4c8067bac9a726f9eb35132c6e7d74 to main
dec3fed HEAD@{1}: checkout: moving from main to dec3fed
3bfd8f7 (HEAD -> main) HEAD@{2}: commit (amend): partially staged
dec3fed HEAD@{3}: commit: partially staged
0173e3b HEAD@{4}: commit: bla
e8886bd HEAD@{5}: commit (initial): initial commit

Hard reset

There might be situation where you want to reset everything to a specific snapshot. Here you can use a hard reset. Be warned, this will reset your working directory and staged files. Every change will be lost.

Make note of your current directory content and status, then perform a git reset --hard HEAD to reset everything to your last commit.

Question

Walkthrough

$ ls -l

total 16
-rw-r--r-- 1 martin martin 16  8. Jun 14:34 commit_me.txt
-rw-r--r-- 1 martin martin 23  8. Jun 14:34 do_not_stage.txt
-rw-r--r-- 1 martin martin  0  8. Jun 15:11 forgotten.txt
-rw-r--r-- 1 martin martin 55  8. Jun 14:34 partially_stage.txt
-rw-r--r-- 1 martin martin 18  8. Jun 14:34 stage_me.txt
-rw-r--r-- 1 martin martin  0  8. Jun 14:34 working.md

$ git status --short

 M partially_stage.txt
?? do_not_stage.txt

$ git reset --hard HEAD
HEAD is now at 3bfd8f7 partially staged

$ ls -l

total 16
-rw-r--r-- 1 martin martin 16  8. Jun 14:34 commit_me.txt
-rw-r--r-- 1 martin martin 23  8. Jun 14:34 do_not_stage.txt
-rw-r--r-- 1 martin martin  0  8. Jun 15:11 forgotten.txt
-rw-r--r-- 1 martin martin 19  8. Jun 15:16 partially_stage.txt
-rw-r--r-- 1 martin martin 18  8. Jun 14:34 stage_me.txt
-rw-r--r-- 1 martin martin  0  8. Jun 14:34 working.md

$ git status --short

?? do_not_stage.txt

Untracked files are not affected, but the modified file is reset.