How to Revert a Commit and Create a New Revert Commit in Python
Demonstrates a mock Git repository that creates a new revert commit on top of the current head when reverting an existing commit.
Python code
52 linesclass GitCommit:
"""Minimal mock of a git commit for demonstrating revert behavior."""
def __init__(self, sha, message):
self.sha = sha
self.message = message
self.parent = None
class GitRepository:
"""Mock repository tracking a simple commit chain."""
def __init__(self):
self.head = None
self.commits = {}
def commit(self, message):
sha = f"sha{len(self.commits) + 1}"
new_commit = GitCommit(sha, message)
new_commit.parent = self.head
self.head = new_commit
self.commits[sha] = new_commit
return new_commit
def revert_commit(self, sha):
"""Create a new commit that reverses the changes of an existing commit."""
if sha not in self.commits:
raise ValueError("Commit not found")
original = self.commits[sha]
revert_message = f"Revert \"{original.message}\""
revert_commit = self.commit(revert_message)
return revert_commit
if __name__ == "__main__":
repo = GitRepository()
c1 = repo.commit("add feature A")
c2 = repo.commit("fix bug in B")
c3 = repo.commit("refactor C")
# Revert the first commit; creates a new revert commit on top
revert = repo.revert_commit(c1.sha)
print(f"Original commit: {c1.sha} - '{c1.message}'")
print(f"New revert commit: {revert.sha} - '{revert.message}'")
print(f"Current head: {repo.head.sha} - '{repo.head.message}'")
# Demonstrate the linear chain
chain = []
current = repo.head
while current:
chain.append(current.sha)
current = current.parent
print("Commit chain (newest -> oldest):", " -> ".join(chain))
Output
Original commit: sha1 - 'add feature A'
New revert commit: sha4 - 'Revert "add feature A"'
Current head: sha4 - 'Revert "add feature A"'
Commit chain (newest -> oldest): sha4 -> sha3 -> sha2 -> sha1
How it works
The GitRepository class maintains a simple linked list of commits through parent references, simulating a linear Git history. revert_commit looks up the target commit by SHA, then calls commit to append a new revert commit whose message is Revert "<original message>". The new commit becomes the head, so the history remains linear and the revert is visible as the latest action. The chain printed in the example walks from head back through parent links, showing the full history.
Common mistakes
- Forgetting to set the `parent` of the revert commit, which breaks the chain
- Reusing the original SHA instead of generating a new one for the revert commit
- Assuming reverting removes the original commit instead of adding a new one on top
Variations
- Model commits with a `changes` set and apply reverse patches for a more realistic revert
- Use a `git` CLI wrapper with `subprocess` for an actual repository
Real-world use cases
- Teaching Git revert semantics by modeling commit history in a simulation or test harness.
- Prototyping CI automation that reverts a bad release by creating a revert commit programmatically.
- Building a toy version-control tool for educational demos or interview practice.
Sponsored
More from Git + Python
- Amend Last Commit Message in Python easy
- Bisect Good Bad Automation Script in Python easy
- Build a Simple Log Graph in Python easy
- Bump Semantic Version Git Tag in Python easy
- Count Unique Contributors from Git Shortlog in Python easy
- Create a Mock GitHub Release API in Python for Testing gh CLI easy
Keep learning
Related tutorials and quizzes for this topic.