17 ms·
Commits are snapshots not diffs (2020)
- ashton314 6y agoI really liked this video: the guy first walks you through how to build your own git-like utility with a handful of shell commands, then goes and walks through an actual git repo: https://youtu.be/qq_s2Hh--aQ https://youtu.be/qq_s2Hh--aQ Even the first 20 minutes was enough for me to have a substantially better understanding of how git works.
- aszen 6y agoI just finished watching this and have to say it is a great talk to understand git. Once you go through the initial 20 mins building a git like utility with bash the rest of the talk about git becomes easier to follow. I recommend building the git like utility in bash yourself first, playing with it for some time and then watching the rest of the talk.
- gpspake 6y agoI think it's a tragedy that just about every developer uses git but most learn add, commit, branch, and merge and then just stop learning. A lot of people are scared of rebase and cherrypick and shut down or get defensive when you mention them or try to encourage their use. The result is, because developers only have a hammer, they brute force merge everything which results in grotesque conflict resolutions and commit histories and makes it hard to untangle problems. At a previous job, another developer was kind enough to walk through rebasing on the command line with vim. I was receptive and in about 10 minutes, I realized there was a significant set of standard features and day to day Git use I was previously just oblivious to. These days, the UI for rebasing and cherry picking in Gitkraken is state of the art and effortless and I use them every day without hesitation and without the fear that comes from not understanding or knowing what I'm doing. Still, I constantly struggle with coworkers merging feature branches from 100 commits ago in to new feature branches and brute force resolving conflicts across half a dozen files in one commit without any context. I see it all because I have visibility in to the history and branch relationships but I still get shrugs and eye rolls when I bring it up. I don't necessarily want to dictate nitpicky git usage but I have a hard time accepting when people just to refuse how rebasing and cherrypicking work when they're both core basic features of a tool we all use every day. Proper Git use is one of those hills I'll die on, though so I don't intend to shut up about it any time soon :) Edit: My practical advice: If you use git every day and you don't know how to rebase, reset, cherrypick, and stash from the command line, make it a goal. Then, once you're comfortable, learn how to do it in a visual tool like Gitkraken and make an effort to incorporate them in to your daily workflow. My guess is things will become a lot less tedious and confusing when things get messy.
- dr-detroit 6y agoNOBODY on my team learned ANYTHING about git. They stopped using it on new projects its like everyone considers their (shabby) work proprietary. Thank you for coming to my TED talk: life is suffering
- forrestthewoods 6y ago> I think it's a tragedy that just about every developer uses git but most learn add, commit, branch, and merge and then just stop learning. This is because Git is too hard to use. How do I know that Git is too hard to use? Because there are literally thousands of blog post tutorials explaining how easy Git is to learn. Things that are easy do not need thousands of different guides telling you how easy it is.
- JadeNB 6y ago> This is because Git is too hard to use. > How do I know that Git is too hard to use? Because there are literally thousands of blog post tutorials explaining how easy Git is to learn. Things that are easy do not need thousands of different guides telling you how easy it is. I'm not sure that's convincing. I think that a lot of guides about how easy it is indicate that it's slightly difficult to learn. That results in a lot of people struggling for a little bit, overcoming the struggle, and feeling a sense of accomplishment and enlightenment, which they then want to share. (There's also a difference between how hard something is to use and how hard it is to learn. I'd argue that there's often a trade-off to be made, where some sacrifice on difficulty learning results in a reward in ease of use—in the sense that, for example, vim is far easier to use than any other editor for a seasoned vimmer.)
- gkoberger 6y agoThe counter argument would be that maybe git is so basic and easy to learn that everyone feels comfortable enough with it to write a tutorial? I think a large amount of content is more a factor of Git's ubiquity than its difficulty.
- Supermancho 6y ago
- aarchi 6y agoWhereas in Pijul and Darcs, commits (called patches) are diffs, not snapshots. They are based on a sound theory of patches, which allows for operations not supported by Git like commuting, as long as the commits aren't interdependent. Plus, language-specific tools can extend the notion of dependency from line-based to semantic.
- luhn 6y ago> They are based on a sound theory of patches, which allows for operations not supported by Git like commuting, as long as the commits aren't interdependent. This is definitely supported by git. Even though commits may technically be snapshots, you can build a diff from snapshots (and vice versa). `git diff` will get you the diff for any given commit, and `git rebase` will happily reorder commits for you by reapplying the diffs.
- rnhmjoj 6y agoWhen reading a bit about Pijul, a few months back, I had assumed every two patches would commute, and I couldn't image how that could possibly work. Does it really have this limitation? If so, it doesn't look much of an improvement compared to git: I can shuffle "patches" all right using `git rebase -i`. I conceide it can be quite slow, though.
- dan-robertson 6y agoSo not every patch can commute with every other patch: “delete foo” doesn’t make sense until after “add foo” has happened. So patches have dependencies that they must come after, but for lots of vc situations, patches are independent. Sets of patches makes rebasing a branch trivial for example because adding the patches from the master after your patches is equivalent to adding them before. If you would get a merge conflict, you get the same merge conflict whether they are added before or after. But nailing down the logic behind commuting patches can be important too as it can catch subtle problems that might happen with normal snapshot-based merging. Consider some people independently editing branches Bob adds a file with line “foo” Alice pulls Bob’s patch Bob changes “foo” to “bar” Alice changes “foo” to “bar” Bob changes “bar” back to “foo” In Pijul or Darcs you should get a consistent result pulling changes from Bob and Alice no matter what order you do it. But if you use something like git, the order you pull and merge, and if you do it at any intermediate times, might change the resulting snapshot (as well as just the history). The start and end state of Bob’s repo loom the same as snapshots but they are different because Bob changed his mind about the line “bar”—maybe the change didn’t work.
- tsimionescu 6y agoIt's nice to understand this, but I fail to see it helping much in practice. Sure, you'll know why the thing you want to do is hard for git to do, but that wont make it much easier. And without knowing even further implementation details, it's a bad idea to rely on this knowledge. For example, the article states that committing a rename separately from edits in the renames files helps git track the renames. But that's not obviously true from the discussion above, because it's not obvious if, when computing a diff between two commits, git will follow the entire history or just apply the diff algorithm on the two commits. If it were the latter, then it doesn't really matter which order you commit things in, git would simply see commit1: fileA, fileB with contents cA and cB; commit2: fileD, fileE with contents cD and cE, and would do the quadratic work anyway, even if commit1.5 had fileE, fileD with contents cA, cB.
- deleted 6y ago[deleted]
- divbzero 6y agoThis is a good overview of Git internals. If this stuff interests you, Chapter 10 of Pro Git offers similar descriptions of Git objects [1] and Git references [2], and then continues onto Git packfiles [3] which are not covered by OP. [1]: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects https://git-scm.com/book/en/v2/Git-Internals-Git-Objects [2]: https://git-scm.com/book/en/v2/Git-Internals-Git-References https://git-scm.com/book/en/v2/Git-Internals-Git-References [3]: https://git-scm.com/book/en/v2/Git-Internals-Packfiles https://git-scm.com/book/en/v2/Git-Internals-Packfiles
- aequitas 6y agoThis article goes into a little too much detail imho. I have had great success explaining Git to coworkers using post-its, permanent marker and a flip board (no computer!) and going through the steps Git would take (abstractly, not exactly) when performing certain commands. All commits (and their relations) are written down on the board with the marker because they don't change (eg: rebasing just creates a new line of commits). The branches are written down on post-its and can move around (like this article explains, they are just pointers). You can use a whiteboard with non-permanent marking for the working directory and index if you want to go that deep.
- davesque 6y agoNeat overview of some of the core concepts in Git that often go unnoticed. Although I'll say that the fact that commits are technically not diffs doesn't seem to matter much in day to day use. Git does a decent job of abstracting that detail away to the point that you could just as well believe commits are diffs. Also, I want to say that technically I believe Git does use deltas to compress an object's history in the blob store. But the different blobs that comprise an object's history can be thought of somewhat as being separate. Git could just as easily not perform this internal, space-saving optimization and things would all work the same. The SHA hashes would be the same and based on the same input.
- breck 6y agoI think this is incorrect, no? Can’t all commits be turned into patches? Thus, aren’t commits isomorphic to diffs?
- divbzero 6y agoIf you inspect the files in the .git directory, you’ll find commits stored as trees of directory and file objects. But it is true that they can be converted diffs on the fly, which is exactly what the git show command does.
- lann 6y ago> aren’t commits isomorphic to diffs? Nearly, though renames are only approximately extracted from the snapshots.
- jepler 6y agoIf your VC isn't plumbed all the way into your editor, you can't tell changing a typo from deleting and re-typing the whole file when it comes time to create a delta.
- lann 6y agoThere is a `git mv` command that means "rename". Git could (even with its current data model) explicitly annotate commits with this intent, but doesn't. I don't know how useful that would be compared to the current heuristics, but it does mean that git commit "snapshots" are not (quite) isomorphic to a diff format (like posix diff's) that can explicitly encode renames.
- tomtomtom777 6y agoConsider a small commit with spelling error. If I turn this into a patch and apply it to another branch it will be a different commit even it will be the same patch. As such, the concept of a "commit" in Git refers to a complete state of everything; a snapshot.
- jepler 6y ago
- zwieback 6y agoCherry-pick is what messes up the commit-as-snapshot idea for me. If I see a small commit that I feel I can merge into my branch then that commit feels like a diff and I don't want to care about the rest of the stuff that commit snapshots. I guess that's a good thing.
- SamBam 6y agoI tend to agree. I am not someone who has a deep understanding of the inner-workings of git by any means, yet I am perfectly comfortable with rebasing and cherry-picking. For me, git is so much easier to intuit if I only think of it as diffs. When I rebase, I'm just rearranging diffs, or squashing them together, or whatever. If I try and think of everything as snapshots it actually gets more confusing for me.
- jasonwatkinspdx 6y agoSo, I think a useful simple way to think of it is "git creates diffs when it needs to on demand." When you're doing a cherry pick of say commit ce123, what you're asking git to do is: 1. Diff ce123 against its parent 2. Go apply that diff to some other branch Likewise rebasing is the same, but with an extra step to apply the inverse of the diff to the original commit first, then rewrite the history. One of the big advantages of this on demand diffing approach is it's much more robust vs conflicts. Back in the subversion days I wrote some shell scripts that did the equivalent of git cherry pick and rebase. I'd keep a couple extra copies of a checkout, would use the switch command to quickly put them into a specific state, then would just generate a diff manually to apply to my main working copy. It worked, and was often faster than manually copying text around between editor windows, but it was extremely conflict prone. So this distinction, of whether you store snapshots and diff on demand, or store diffs and snapshot on demand, is somewhat subtle but has important consequences.
- zwieback 6y agoYeah, good summary.
- 6y ago
- deleted 6y ago[deleted]
- whack 6y agoFrom a storage perspective, describing commits as snapshots seems like a bad mental model. Suppose I have a directory that is 100MB in size. If I take a snapshot of it, my snapshot would be 100MB in size. If I take a 2nd snapshot of it tomorrow, my 2nd snapshot would also be 100MB in size. My total storage needs would now be 300MB. Whereas if I had used git, and created 2 additional commits, each making a change to a small text file, my total storage size would be barely larger than 100MB. Describing the commits as a diff, as opposed to a snapshot, leads to a better intuitive understanding of why this would be the case. Not to mention other features the article discussed, such as cherry-picking. What does it even mean to "cherry-pick a snapshot"? In comparison, cherry-picking a diff and applying it to your current state, is far more intuitive. And let's not forget commit messages. If a commit is a snapshot, I would expect the commit-message to be descriptive of the entire snapshot. Whereas if a commit is a diff, I would expect the commit message to be descriptive of the diff. Which is exactly how most people use commit messages. Obviously both "diffs" and "snapshots" are leaky abstractions. If you insist on using the "snapshot" abstraction, you will need to resolve all of the above points of confusion by adding more complexity to your abstraction. And if you prefer to use the "diff" abstraction, you will eventually need to explain that a commit is actually a combination of diffs, along with some other metadata like a pointer to a parent commit. As a teaching tool, you can make either abstraction work. But I find it far more intuitive and useful to think of commits as "diffs + some metadata".
- dbt00 6y agoif your filesystem was copy on write and implemented snapshot semantics internally (like WAFL for example, over 20 years old now), then the second snapshot would not take 100MB, it would just cost the metadata. A commit is a snapshot of a tree with a reference to it's prior ancestors. It's important to know that because it becomes extremely relevant when trying to do things like merges properly.
- towergratis 6y agoLookup Copy-On-Write. ZFS and BtrFS do it.
- jayd16 6y agoDepends on the diff. If the diff is not aligned by bits a single bit offset might cause double the size, ie the full file to delete and a full file add. >If you insist on using the "snapshot" abstraction But its not insisted. Both abstractions are used as needed.
- rhabarba 6y agoDarcs users disagree.
- samatman 6y agoThis blog post is the most compelling argument I've yet seen for pijul. Git should work the way we think it does! It's confusing that snapshots are being converted into a few different forms of change object, which can be reconciled with merges or rebases or applying patches. Pijul (and darcs before it) actually works on the basis of patches, pijul with a robust theory of patches. A cherry-pick just moves a patch from one history-of-patches (branch) to another history-of-patches. One can share just a patch, and applying it is guaranteed to be the same action everywhere if that's possible, which it often is. I'm patiently waiting for pijul to be mature enough that I can move everything over to using it, it's one of the more exciting projects in the last ten years.
- jayd16 6y agoCan I make a shallow clone in Pijul?
- pmeunier 6y agoI'm one of the authors. The concepts are different, we do have a concept called "tags" (not ready yet) which is more efficient than shallow clones, in the sense that you can make patches (commits) on top of a shallow clone without any down side (unlike in Git, where shallow repositories can become slower). You can also do partial clones in Pijul: since patches commute, the patches you produce on top of a partial clone can be pushed to the full repository in the exact same way.
- cmeacham98 6y agoNo idea what Pijul is, but how does this not describe git? Unless your complaint is that a commit is really a set of diffs/patches?
- chriswarbo 6y agoPijul (and Darcs) operate on sets of patches. As a simple example, git commits have at least one 'parent', which imposes an order, e.g. let's say I edit file X in commit x and file Y in commit y; if I want both of those changes, git forces me to apply them in a particular order, e.g. [x, y]. If someone else applied those same two commits in a different order, they'll get a different commit ID, which may cause problems e.g. when trying to merge their changes with ours. If we treat x and y as (sets of) patches instead, then the set {x, y} is the same as the set {y, x}; the order doesn't matter (we say those patches commute). The idea of commuting patches is really useful, since we can rearrange patches to a more convenient form. For example, if we commit something we shouldn't (like a password, or a huge binary), then later remove it, a system like git makes it hard to remove that file from the history. If we're dealing with sets of patches, we can simply swap them around until the 'add file' and 'remove file' patches are next to each other, then merge those two patches. Voila, the file no longer appears, the rest of the history remains intact, the branch's content is guaranteed to remain unchanged (since we only swapped commuting patches, which doesn't change anything; and merged two patches, which doesn't change anything).
- slumpt_ 6y agoMost developers think of commits as diffs and they can for all intents and purposes be thought of as such. It’s actually best for the understanding of how to practically get things done to think of them in this way. Odd semantic argument to make.
- maweki 6y agoI think we're running into a naming issue here. It's usefult to think of a single commit in itself as a diff. The DAG is a useful model for an accumulation of changes. The question is, what changes and operations make up a node in the DAG (i.e. what code is in this branch, compared to that? What code do they have in common)? To answer this: take the node and follow along the predecessor until you get one (or more) roots. All commits along the root are contained in the commit at hand. That's the history. Adding changes is, I think, the most useful mental model, even if it is not the implementation. Now what the author is saying is: A commit is not only the diff, but also the whole tree/history that the diff is based on. And that is also true and then the commit (the adding plus the past) is a snapshot. Do we have a good naming convention for the single node in the tree with its changes, compared to the single node in the tree with its changes AND the references to the parents with all their changes etc.?
- derriz 6y ago> It's usefult to think of a single commit in itself as a diff. Except if it has multiple parents like a merge commit. Actually I don’t agree even in general. It took me an unreasonably long time to become unafraid of git because I clung to the common VCS mental where commits were actually diffs.
- maweki 6y agoBut the snapshot-model also doesn't really make a lot of sense for merges. It's a snapshot of what then? A merge of all parent trees? What's a merge of two files then? Defining this merge-operation on trees is at least as mentally taxing as the alternative. Accumulating all the diffs from two (or more) ends (until they are common again) is at least as useful.
- derriz 6y agoFor me, a merge commit in git is just a snapshot like any other except that its metadata contains links to more than one parent. The parent child relationship acts as nothing more than remark that the child was derived from both parents in some way. Of course, commonly the child is derived by finding the most recent common parent, using heuristics to guess file identities after any renaming and then performing a 3-way line-based diff between what it thinks are corresponding files. But actually git doesn't really care - it's just another snapshot you've created and added to the DAG. I haven't found it helpful to think of what's going on in git in terms of an "accumulated file diffs" abstraction because git has no notion of file identity (across commits).
- cryptonector 6y agoYes, exactly, this is a very good post on the nature of Git. > Branches are pointers Yes. I would say they are named pointers. Commit hashes are weak, unnamed pointers.
- mberning 6y agoAm I the only person that doesn’t want to understand the inner workings of my VCS in lurid detail? I don’t have to know as much about any other developer tool in order to use it effectively.
- outworlder 6y ago> I don’t have to know as much about any other developer tool in order to use it effectively. You don't? How do you debug problems?
- mberning 6y agoI just use the debugger and it mostly works how I expect. I don’t have to go and study the data structures and other intricacies of the debugger itself to puzzle out why it works the way it does. Git is terrible in that way, as evidenced by the thousands of blog posts of people trying to describe the inner workings of it and how it will “make more sense” once you understand it as well.
- bombcar 6y agoThink about ZFS - ZFS works perfectly fine for me and I don't have the foggiest idea how it works beyond "copy on write" magic.
- detaro 6y agoDo you feel like you need to know this to use git? What did the blog post change about your use of git?
- ndand 6y agoI used to think commits as snapshots, but it was confusing. Then I read "Git Internals". A commit contain the "whole" content of each file that we've commited. But since a commit has a pointer to a root commit, it also represents a working directory. Even though a commit contain "whole" files, the git internally stores only parts of the files as an optimization. When we diff two commits, we see the difference of the file contents in the corresponding working directories that the commits represent.
- deleted 6y ago[deleted]
- necovek 6y ago> I believe that Git becomes understandable if we peel back the curtain and look at how Git stores your repository data. I agree, and like many, I have been saying that for years (nay, for more than a decade): and that's exactly the problem! You don't need to understand how an internal combustion engine works to drive a car... You don't need to understand how your graphics card renders stuff to develop a web page... You don't need to know how a brushless motor works to use a drill... There is a pattern there, and it's the one that makes sense. I've read up on the internals of git a dozen times by now. But I only occasionally need to do something weird that makes me go back to it, so I usually forget the relevant bits. The trouble is that I've used a distributed VCS that did not ask me to understand internals and it had a sane UI, and good model (like tree-like commit history, so a top-level commit log would only have merges, but you could dive deeper into individual commits if you so pleased). It wasn't perfect, but it's hard for me to accept that we have gone with a subpar solution where every "tutorial" starts with how you need to understand the internals! But you also need to memorise them, dammit! Just like I keep forgetting the Emacs rectangle editing shortcuts since I seldom use them, I'll keep forgetting the specifics of git internals that I might need once every 12 months. And it's not me, it's _you_, git!
- mdnahas 6y agoSadly, the bad part is git's user interface. It hides the pretty parts underneath. There is a concept of "the next commit" or, equivalently, "the pending commit". In the documentation, this gets called "indexed" or "cached" or "staged" --- three different names! And if you want to diff with it, you can't refer to it by name. You need to use an option, so it's "git diff --cached <other commit>. I know git's internals, mostly because it lets me navigate its bad user interface.
- leni536 6y agoCommits being snapshots is not git internal. It is the high level abstraction.
- sergeykish 6y agoBut you have to know how ICE works to resolve issue. Oil pressure? Engine temperature? Leaking radiator? Gas pump? Dead battery? Wet spark plugs (on older models)? But there is more — air filter, oil filter, oil change, mechanical parts — these usually resolved by handling car to professionals, and they have to know how system works. You have to understand DOM to resolve web page issue. Understanding how graphic card works would help in resolving webgl issues.
- ChrisMarshallNY 6y agoThat's a cool explanation. I'm a bit slow on the uptake, so I had to re-read a couple of sections, but it was helpful.
- dmuth 6y agoIf anyone does want to get more into the internals of Git without playing with a production repo, I built a "playground" awhile ago which creates a simple Git repo of synthetic commits which you can then play around with: https://github.com/dmuth/git-rebase-i-playground https://github.com/dmuth/git-rebase-i-playground I know it says "rebase -i", which originally what I built it for (and what the exercises in the README are for), but you can really do whatever you want in it, and blow away/rebuild the repo with the included script. Enjoy!
- siawyoung 6y agoCommits are conceptually snapshots, and everything else Git does is just an optimization over the naive “keep all versions of all files ever” (imagine implementing a version of Git that is just zipping the entire folder). Diffs are isomorphic to commits and are generated as needed. I wrote about it (albeit imprecisely) here: https://siawyoung.com/git-intuition https://siawyoung.com/git-intuition
- masukomi 6y agothis... seems so very flawed and disprovable to me. Ignoring the obvious storage issues that have been discussed if commits were snapshots you could rebase and reorder them without ever worrying about conflicts. In reality you very much DO have to worry about conflicts because they are change instructions that transform a file from A->B->C if you try and reorder it as A->C->B you're going to have serious issues (assuming these all touch the same code) because C is a transformation from the B state to the C state. It blows up attempting to convert A->C because the instructions in that transformation describe going from B->C. > A commit is a snapshot in time. Each commit contains a pointer to its root tree, it so... _so_ very much isn't. It's not even a snapshot in time of a section of a file. It's a change instruction. No, it's not a "diff" but it also isn't a snapshot.
- nyanpasu64 6y agocommits are snapshots. cherry-picking/rebasing diffs a commit and its (first?) parent, and applies the diff on a base commit to create a new commit. if you `git replace` a single commit and change its contents, its children do not change their contents, so `git show`ing any direct child will show a new diff, not previously present, reverting the actions you've performed in `git replace`.
- grawprog 6y ago>Commits are snapshots....commits are diffs.... Neither model really encompasses commits for me. I prefer... Commits are a point in history I can return to after I inevitably fuck up or look back on so I can convince myself, yes I am indeed making progress.
- iudqnolq 6y agoWhy have so many people written long thoughtful explanations about how the author is wrong to suggest snapshots are a better mental model, and that you think all abstractions are leaky, but you find diffs a better mental model? The entire article is literally about how commits are literally snapshots. I would say people didn't read TFA, but a lot of people are quoting lines from TFA and then going on to argue with/expand on them in a way that is directly contradicted by the next few lines. I think it's because most of the people here have spent years working with git, and are so deeply attached to their understanding that they didn't hear most of what the article said. (Some commentators have pointed out specific oversimplifications the author makes like glossing over pack files, I'm referring to the people who say a git blob is a diff when the entire point of TFA is that it isn't)
- nightpool 6y ago> Why have so many people written long thoughtful explanations about how the author is wrong to suggest snapshots are a better mental model, and that you think all abstractions are leaky, but you find diffs a better mental model? Probably because, to take their words at face value, they find diffs a better mental model? I think impugning "people [...] are so deeply attached to their understanding that they didn't hear most of what the article said" is a real bad faith reading, especially when you even acknowledge that central to people's arguments is "all mental models are leaky". This article may be technically correct about the way git internals are structured, but it makes cherry-pick and rebase more mentally complex for users to understand (you first have to go from commit => patch), not less. Saying "Commits are collections of files + a parent commit, but you can diff it to generate a patch" and saying "Commits are a patch + a parent commit, and you can apply it to generate a collection of files" are isomorphic mental models—the fact that #1 is "correct" (for some value of correct that doesn't include the actual files stored on disk) is really besides the point.
- iudqnolq 6y agoMy point is that people criticizing TFA's proposed mental model are missing the fact that TFA doesn't propose a mental model, it explains how things work. Both have value, but they're distinct.
- Tomminn 6y agoIt strikes me as bizarre that something as old and as important as git is to the general version control problem, doesn't have a beautiful, complete and helpful user interface. With the status quo how it is, I definitely love articles like this because every time I use git I get a kind of anxiety that fades only in proportion to the depth with which I understand actual git mechanics. The thing I find strange is that when I interact with databases that have beautiful, helpful user interfaces, I have almost none of this anxiety, and just kind of accept "black box that handles things", and move on with my life. I figure I must not be alone in this psychological niche. Which again, makes it bizarre that the problem of giving git a beautiful, complete, helpful front end has not been solved.
- SCLeo 6y agoI can't agree with you more. git commands are definitely not designed for the current main stream usage (i.e. with services like GitHub/GitLab). Simple things like forking a repo from another user and edit locally requires >10 non-straight forward steps is far from ideal.
- mekkkkkk 6y agoThere are so many tools to help with this though? If you want to work with Github, there is an official Github CLI tool that makes forking easy peezy. Gitlab doesn't have an official one AFAIK, but there are unofficial ones. And if you want GUI there's a myriad of those as well. I don't understand this complaint at all.
- motoboi 6y ago> It strikes me as bizarre that something as old and as important as git is to the general version control problem, doesn't have a beautiful, complete and helpful user interface. It has several. Tower is a wonderful interface in MacOS, Sublime-Merge too. Github is another, Gitlab also a very good. Gog is a free as in beer option too. There are several. None has dominated the market, tough.
- Tomminn 6y ago
- deleted 6y ago[deleted]
- Tomminn 6y agoGreat article but: "one of my favorite analogies is to think of commits as having a wave/partical duality.." is a hilariously misguided object to build an analogy from. Theoretical physicist checking in, and my community has been searching for about 100 years for an analogy to explain that shit, so it's hilarious to see someone try to use it as a concrete object people can use as a touchstone to better understand a purely classical database.
- bombcar 6y agoRead it as "think of commits as <unintelligible bullshit you have to take on faith because nobody really understands it>"
- d_tr 6y agoMy first tutorial was the Pro Git book, and this fact was stressed well there so it stuck. Thinking of commits as snapshots also has the small advantage of making the first commit less special.
- karmakaze 6y agoThis comes up from time to time and each time the comments debate the correctness/effectiveness of the title. The contents of the post does shed much light on how git operates and introduces a view that can help in navigating how to use git. Whether or not you want to think of a commit as a snapshot or a diff isn't material. It's best to think of it as a dual, since a diff on any base can create a snapshot, and a snapshot can create a diff from a snapshot. This very much mirrors the idea of a transaction log (of diffs) and a 'current' state. The current state is convenient, can benefit performance, but is not absolutely necessary. It doesn't even have to be the most recent, e.g. key frames in video compression. These are all just ideas, getting used to them and being able to move viewpoints between them is better than clinging to any one of them.
- fraculus 6y agoI think merge commits are key to why "snapshots" are a better model than "diffs", and a stronger arguments would emphasize this more. Like people have said, the two models: - a commits is a snapshot plus a pointer to a parent commit - a commits is a pointer to a parent commit plus a diff are sort of isomorphic. And some commands in the git porcelain (like git cherry-pick, or git rebase) indeed make more sense if you think of commits as diffs. But this isomorphism becomes really strained when you have commits with more than one parent (or even zero parents). (And I think it's telling that those commands don't play very nicely with merge commits or the root commit.) If you really want to incorporate merge commits and the root commit, the alternatives become: - a commit is a snapshot, together with a list of zero or more pointers to parent commits - a commit is a list of M >= 0 pointers to parent commits, together with N > 0 diffs, subject to the invariant that: a) M = N, except that for exactly one commit, which we will call the "root" we are allowed to have M = 0 but N = 1 b) starting from any commit, if you traverse a path back to the root commit by following parent pointers, and then sequentially (in reverse order) apply, for each commit in the path, the diff that corresponds to the parent pointer chosen, then the result of composing all those diffs is independent of the path chosen. And when you put it like that, it's pretty clear that the "diffs" model is really impractical, and that's why it's a lot better to think of commits as snapshots.
- hongsy 6y agoi convinced myself that commits are snapshots by doing the following: # generate a 100M text file base64 -b 76 /dev/urandom | head -c 100000000 > file.txt git add . && git commit -m "1" # remove first line and add a new line to bottom tail -n +2 file.txt > tmp && rm file.txt && mv tmp file.txt && base64 -b 76 /dev/urandom | head -n 1 >> file.txt git add . && git commit -m "2" # repeat tail -n +2 file.txt > tmp && rm file.txt && mv tmp file.txt && base64 -b 76 /dev/urandom | head -n 1 >> file.txt git add . && git commit -m "3" ... du -sh . # a very big folder each of the commits are almost 80M big in the git folder. if you run `du -h .` you can see how git stores each object individually (80M big)
- rektide 6y agosimonedon chuckles in allagmatic.
- da39a3ee 6y agoThe fact that in the implementation “commit” means one thing, does not mean that people need to / should use “commit” to mean the sane thing, not that it is necessarily helpful to do so. In any case a commit is more than a snapshot because it has a parent, thus diff is a sensible mental model for the pair.