3 ms·
Can someone explain the change set data structure, specifically how you can re-apply it to different revisions of the repo? - Is it just a diff with paths and
by klabb3 4y ago
Can someone explain the change set data structure, specifically how you can re-apply it to different revisions of the repo?
- Is it just a diff with paths and specific line numbers?
- Does it contain a few lines of context to heuristically map the diff onto the right place in case unrelated lines are added/removed?
- What other data structures are needed to produce a snapshot? Is it just a graph of change sets?
- fuckstick 4y agoGit internally doesn’t deal in diffs - the conceptual objects are blobs, trees and commits. A tree is like a directory structure of blobs (basically whole files) and commits link trees in a graph. It’s a graph of filesystem like trees basically - not changesets. Very conceptually simple - hence the stupid “git” content tracker. Git has a pack file format that stores deltas but that is just for space saving.
- kevincox 4y agoThe logical model of Git doesn't store changesets or diffs at all. The logical structure of a commit is: 1. Some "human" metadata such as message, author, timestamps 2. An ordered list of parents (0 to infinity parents) 3. A complete directory tree of the repository at that version. So when you reference a commit in Git you aren't referencing a diff/changeset. You are referencing an exact snapshot of the files in the repository at that time. This is sometimes obscured because to a human we often find it useful to see what changes a commit introduced. For example if you run `git show $commit` in the simple case where $commit has exactly one parent Git will compute a diff between $commit and its parent ($commit~1). However logically this diff isn't stored as part of the repository, it is computed on the fly from the snapshots of the two directory trees. If you want to re-apply it to a different version of the repo (usually via `git cherry-pick`) Git basically does two steps: 1. Compute the diff between the commit and its parent. 2. Apply that diff to the target revision. Of course this all gets more complicated in the case of merge commits (commits with >1 parent) but the model is similar. (For performance reasons Git does use delta compression internally but that is just an optimization and doesn't really reflect the diffs that humans are interested in).