TT Lab
Get started
Learn Learning paths Courses

Git in Practice

reset, revert and reflog in Practice

Continue in TT Lab

Goal

You run the three reset modes, amend, revert and reflog, each in an independent repository, compare the results, and summarize in a cheat sheet what to use in each situation. Put the deliverables under /root/gitx2/.

Why it matters

Most undo accidents arise not from not knowing the command but from running it without knowing what it overwrites. --soft loses nothing, the default --mixed loses only the staging state, and --hard loses all uncommitted changes. Rate the danger not by the command name but by "does this command overwrite uncommitted changes?". And there is a second axis. If a commit is already in someone else's repository, every way of eliminating it breaks other people's history. In that case, appending instead of altering the history is the answer. This lab lets you confirm that difference not by words but by commit counts and file existence.

Steps

There is no global git identity. Every time you create a repository, you must set a local user.email / user.name for commits to work.

  1. Create /root/gitx2/mkrepo.sh and chmod +x it. In the path received as the first argument ($1) (creating it if it does not exist), initialize a repository, with the branch main and 5 commits. The nth commit adds fn.txt (f1.txt … f5.txt) and its subject is c1 … c5. The grader runs this script in a temporary directory to check, so do not hard-code the path; be sure to use "$1".
  2. Create a repository with the script at /root/gitx2/amend, and change only the subject of the last commit to c5 fixed. The commit count must stay at 5, an amend record must remain in the reflog, and the hash before the change and the current hash must differ.
  3. Create a repository at /root/gitx2/soft and undo one commit. Result: 4 commits, f5.txt staged in the index, and f5.txt also present in the working tree.
  4. Create a repository at /root/gitx2/mixed and undo one commit. Result: 4 commits, f5.txt not staged, and it must remain in the working tree (in git status --porcelain, ?? or M).
  5. Create a repository at /root/gitx2/hard and undo one commit. Result: 4 commits, f5.txt gone, f4.txt still present, and the working tree must be completely clean.
  6. Create a repository at /root/gitx2/revert and cancel out only the change of the c3 commit. Result: 6 commits, a commit whose subject starts with Revert exists, the original c3 commit must also remain in the history as it is, and f3.txt must be gone while f1/f2/f4/f5.txt remain.
  7. Create a repository at /root/gitx2/reflog. Before undoing, save the current HEAD hash to /root/gitx2/before.txt (only the hash string must be in the file). Then forcibly discard 2 commits, look at the reference log, and recover to the original position. Result: HEAD must equal the hash you recorded and there must be 5 commits, and a reset record must remain in the reflog.
  8. Write a cheat sheet in /root/gitx2/undo.md. The text must contain all of --soft, --mixed, --hard, revert and reflog, and must have the three lines below.
    • pushed= — the command to use when undoing a commit you already pushed and others have pulled (one word)
    • staging_only= — the reset option that releases only the staging and keeps the files
    • worktree_wiped= — the reset option that also discards uncommitted changes

Notes

Create a repository-creation script

Create /root/gitx2/mkrepo.sh and chmod +x it. In the path received as the first argument ($1) (creating it if it does not exist), initialize a repository, with the branch main and 5 commits. The nth commit adds fn.txt (f1.txt … f5.txt) and its subject is c1 … c5. The grader runs this script in a temporary directory to check, so do not hard-code the path; be sure to use "$1".

/root/gitx2/mkrepo.sh creates a new repository at the path received as its first argument. The path may not exist yet, so you must create it first, and since there is no global identity, you must set a local identity in each repository for commits to work. Do not forget chmod +x.

Fix the last commit message

Create a repository with the script at /root/gitx2/amend, and change only the subject of the last commit to c5 fixed. The commit count must stay at 5, an amend record must remain in the reflog, and the hash before the change and the current hash must differ.

Stamp out a repository at /root/gitx2/amend and change only the subject of the last commit. An amend does not increase the commit count, but it creates a new commit object, so the hash changes, and the previous hash remains in the reflog.

Undo the commit only and keep the staging

Create a repository at /root/gitx2/soft and undo one commit. Result: 4 commits, f5.txt staged in the index, and f5.txt also present in the working tree.

In /root/gitx2/soft, undo one commit, but the changes must remain in the index as they are. It is the mode, among the three, where you lose nothing.

Undo up to the index

Create a repository at /root/gitx2/mixed and undo one commit. Result: 4 commits, f5.txt not staged, and it must remain in the working tree (in git status --porcelain, ?? or M).

In /root/gitx2/mixed, undo a commit, but the staging must be released and the file must remain in the working tree. This is exactly the default behavior when you add no option.

Undo up to the working tree

Create a repository at /root/gitx2/hard and undo one commit. Result: 4 commits, f5.txt gone, f4.txt still present, and the working tree must be completely clean.

In /root/gitx2/hard, the file must disappear along with the commit. It is the only mode that overwrites uncommitted changes, so you must always think once more before running it.

Undo while keeping the history

Create a repository at /root/gitx2/revert and cancel out only the change of the c3 commit. Result: 6 commits, a commit whose subject starts with Revert exists, the original c3 commit must also remain in the history as it is, and f3.txt must be gone while f1/f2/f4/f5.txt remain.

In /root/gitx2/revert, cancel out the change of only one middle commit. The history must not shrink; instead, one commit must be added. For a commit that has already gone to other people, only this method is safe.

Recover a lost commit

Create a repository at /root/gitx2/reflog. Before undoing, save the current HEAD hash to /root/gitx2/before.txt (only the hash string must be in the file). Then forcibly discard 2 commits, look at the reference log, and recover to the original position. Result: HEAD must equal the hash you recorded and there must be 5 commits, and a reset record must remain in the reflog.

In /root/gitx2/reflog, first write the hash from before the undo to a file, deliberately discard commits, and then look at the reference log and return to that position. before.txt must contain only the hash string.

Summarize the cheat sheet by situation

Write a cheat sheet in /root/gitx2/undo.md. The text must contain all of --soft, --mixed, --hard, revert and reflog, and must have the three lines below.

In /root/gitx2/undo.md, mention all three modes plus revert and reflog, and write the correct answer for each situation in the three lines pushed= / staging_only= / worktree_wiped=. For a commit that is already pushed, do not use a command that alters the history.