Learn system design from Git - Event Sourcing
The fundamental requirements of a version control system can be summarized as: 1. Keep track of what happened in history using versions 2. Allow users to go back to any moment (version) of history to recreate the snapshot of that moment 3. Allow users to work on their own perspective (branch) of history without interfering each other 4. Allow different branches of history to easily reconcile, to create new version of history When we compare these requirements to the idea of event sourcing - āensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied for the same lifetime as the application state itself.ā, we can see Git is a by the book implementation of the Event Sourcing design pattern. Git models all the mutations in history as immutable event objects: the mutation on a file is a blob object; the mutation on a directory is a tree object; each commit is just another type of event object that represents a checkpoint of the history. āA commit specifies the top-level tree for the snapshot of the project at that point; the parent commits if any; the author/committer information (which uses your user.name and user.email configuration settings and a timestamp); a blank line, and then the commit message.ā Now with this simple yet powerful abstraction, a branch in Git is just a reference pointer to a commit. A branch allows users to get a view of their preferred version of history, and create new history from there. Reconciling different branches is really simple in an event sourcing system. 1. You can merge two branches, which basically to create a commit object with two parent commits - from the last commits of the two branches. 2. Or you can rebase two branches together first, which replays the events from one branch on another. Then when you merge the two branches, it is a simple āfast forward mergeā, the new commit objects will only have one parent commit. The rebase operation is quite literal - it creates new commits out of existing commits to give them another ābaseā (parent commit), to avoid the complexity of having two parent commits. If you imagine your mom and dad yelling at you at the same time for different reasons, you know why having one parent commit is a simpler solution. The reason rebase can work so well in Git is because Git is an event sourcing system: replaying commits from one branch to another is easy in event sourcing. Now we can understand what tags are in Git and how tags are different from branches. Tags are immutable pointers to commit objects. You canāt create new commits on top of tags. Branches in Git are mutable pointers, you can create new commits on branches. Version control becomes so much simpler in Event Sourcing, doesnāt it? Work hard, have fun, create history and remember to source control everything using Git!
Last updated
Was this helpful?