5 ms·
Git stores diffs, not snapshots. A commit is a changeset, literally a patch that you can export with `git diff`. Ordering of is layered on top of that and infor
by jdbernard 10y ago
Git stores diffs, not snapshots. A commit is a changeset, literally a patch that you can export with `git diff`. Ordering of is layered on top of that and informs things like merges.
Can you explain a little more what you mean?
- qznc 10y agoGit does store snapshots, not diffs. Look into the files in .git/objects/* ;)
- deleted 10y ago[deleted]
- tghw 10y agoNot sure why you're getting downvoted, you're describing git correctly. If anyone is questioning this, just play with `git rebase -i [some old changeset id]` and you'll see that it's just an ordering of patches.
- lvh 10y agogit rebase -i does not demonstrate that gits internal model involves a DAG of snapshots (objects); it only demonstrates that git is sometimes willing to move the contents of one of those snapshots around to create a new snapshot. That is very different from a patches-always model, as I have illustrated in a sibling comment with an example link.
- mst 10y agorebase turns the snapshots temporarily into a stack of patches, lets you play with them, then turns them back into snapshots. In fact, this is why rebase is an out-of-band tool that has odd effects on shared history - specifically because it's inverting git's model into something more like pijul's, and therefore isn't really native-to-git.
- lvh 10y agoInternally, git objects are snapshots -- the differences are computed on demand. That is a critical difference, because it has implications for how merging can work. For example: https://tahoe-lafs.org/~zooko/badmerge/simple.html https://tahoe-lafs.org/~zooko/badmerge/simple.html Even when using git am or send-email or whatever, yes, you're sending a patch -- but the way to apply that patch is to turn it into a commit and then cherry pick or rebase or merge or manually fix conflicts or whatever. In darcs and pijul, the model is _always_ that set of patches.
- jdbernard 10y agoSo, I didn't believe you because my internal mental model of a git repo is a DAG of changesets. And indeed, that is a good way to think about it, because almost all of git's operations behave like this. Commit history is almost always presented to the user as a series of diffs. But, you are correct. Internally, git stores the full contents of files and computes the diffs on the fly. For others' benefit, if you want to test for yourself, create a new repo, add a file and make a series of commits with changes. Git objects are compressed with DEFLATE (zlib) so gunzip and unzip won't work. I used https://github.com/jezell/zlibber https://github.com/jezell/zlibber because I was too lazy to write my own quick zlib wrapper. Then doing for o in .git/objects/*/*; do cat "$o" | inflate ; echo ""; done lists the contents of all the git objects. Notice that there are no changesets, only full copies of the file you modified at different states. This was surprising to me, since I had a very different model mentally. I still think the DAG of diffs is the better model mentally, but it is worth understanding that this is not what git is actually doing under the hood. It explains issues that arise doing rebases, cherry-picks, etc. I now also understand the motivation behind Pijul. If I understand correctly, Pijul does use a collection of changesets as the underlying model. Like you say, that can be a critical difference.