reset, revert and reflog in Practice
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.
- Create
/root/gitx2/mkrepo.shandchmod +xit. In the path received as the first argument ($1) (creating it if it does not exist), initialize a repository, with the branchmainand 5 commits. The nth commit addsfn.txt(f1.txt … f5.txt) and its subject isc1…c5. The grader runs this script in a temporary directory to check, so do not hard-code the path; be sure to use"$1". - Create a repository with the script at
/root/gitx2/amend, and change only the subject of the last commit toc5 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. - Create a repository at
/root/gitx2/softand undo one commit. Result: 4 commits,f5.txtstaged in the index, andf5.txtalso present in the working tree. - Create a repository at
/root/gitx2/mixedand undo one commit. Result: 4 commits,f5.txtnot staged, and it must remain in the working tree (ingit status --porcelain,??orM). - Create a repository at
/root/gitx2/hardand undo one commit. Result: 4 commits,f5.txtgone,f4.txtstill present, and the working tree must be completely clean. - Create a repository at
/root/gitx2/revertand cancel out only the change of thec3commit. Result: 6 commits, a commit whose subject starts withRevertexists, the originalc3commit must also remain in the history as it is, andf3.txtmust be gone whilef1/f2/f4/f5.txtremain. - 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. - Write a cheat sheet in
/root/gitx2/undo.md. The text must contain all of--soft,--mixed,--hard,revertandreflog, 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 filesworktree_wiped=— the reset option that also discards uncommitted changes
Notes
- Script skeleton:
mkdir -p "$1"→git -C "$1" init -q -b main→git -C "$1" config user.email ...→ file creation,git addandgit commit -m "c$i"in a loop. - Saving the hash: if you use
git rev-parse HEAD > /root/gitx2/before.txt, only the hash goes in. If you put thegit logoutput in as is, it fails the format check. - Finding a lost commit: in
git reflog, use notation such asHEAD@{1}, or use the hash shown on the left as it is. - Common mistake 1: continuing steps 3 to 5 in the same repository. Each step must start from a clean state in a separate directory.
- Common mistake 2: using
git resetin step 6. If the commit count decreases, it fails. A revert does not erase the past but stacks one more opposite commit. git revertmay open an editor. If you add--no-edit, it proceeds as it is.
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.
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 filesworktree_wiped=— the reset option that also discards uncommitted changes
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.