6 ms·
I love this quote from Part I: "Git has an elegant and powerful underlying model based on a few simple concepts: 1. Commits are immutable snapshots of the r
by praptak 4y ago
I love this quote from Part I:
"Git has an elegant and powerful underlying model based on a few simple concepts:
1. Commits are immutable snapshots of the repository
2. Branches are named sequences of commits
3. Every object has a unique ID, derived from its content
Built atop this elegant system is a flaming trash pile. "
- eulenteufel 4y agoThe quote is kinda wrong in that point 1 and 2 are mixed up. Branches are just pointers to commits. Commits contain a reference to their history. It's only kind of incorrect because in praxis branches are used to refer to a history (a sequence of commits). But it's also misleading once you have to do anything more complicated than just commiting/merging. When I started out using git I was working with the same assumptions, but I was perpetually confused. Git became a lot easier to use once that misunderstanding cleared up. Maybe it's just like that for me but I think we might be doing newcomers to git a disservice by explaining the basics of git in this simplified manner.
- deleted 4y ago[deleted]
- sophacles 4y agoDo you have an actual example of this? I've never encountered a situation where those three points are incorrect.
- badpun 4y agoGit branch is actually very similar to git tag[1]. For example, there are commands to point branch to completely different commit in different section of the commit graph, just like you can do it with tags. [1] The main difference perhaps is that, if you create a new commit, the branch pointer will actually be moved to point to that latest commit (while tag stays fixed).
- kleinsch 4y agoIf you're in a detached head state and create a new commit, you have a commit that isn't on a branch. The commit still has a parent, so it's not the branch that's tracking the sequence, it's the commit. Branches are just pointers that get updated as you add commits.
- sophacles 4y agoThis feels like declaring squares aren't rectangles because you can make rectangles that aren't a square.
- wonderbore 4y agoGit is only commits. Branches and tags are references to the commits; one moves while the other one doesn’t. That’s it. Commits link to their parent(s) until the initial commit. You can visualize a “branch” as a series of commits, but the same thing can exist without calling it a branch: A -> B -> C —> Initial Is that a branch? No. How about: /refs/heads/main = A That’s a branch, and it looks exactly the same as a tag: /refs/tags/v1 = A Neither a branch or a tag is “a series of commits” even if you think it does.
- deleted 4y ago[deleted]
- sophacles 4y ago> You can visualize a “branch” as a series of commits, but the same thing can exist without calling it a branch You can visualize a "square" as a rectangle with equal sides, but the same thing can exist without calling it a square.
- praptak 4y ago2. is true or untrue depending on how deeply you interpret it. A branch is named, points to a commit and under normal circumstances will track the sequence of commits made via itself (i.e. when you commit and HEAD points to branch b, b starts pointing to the child commit). So you could say it's a named sequence of commits. On the other hand you can reset the branch to any commit in the tree, even ones which aren't even on the current sequence of parents. It is still technically a named sequence of commits, just a totally different one.
- peter_t_wilson 4y ago
- stonemetal12 4y agoGit supports history rewriting so 1 isn't true. Git uses hashes for "unique ids" hashes aren't unique just low probability of collision, so 3 is also not true. Having run into issues that appear to be caused by 3 not being true, I don't see that as a theoretical issue.
- stu2b50 4y ago1 is true. When git is “rewriting” history it’s actually creating a new commits and moving the branch pointer over. Until the gc reaps them, you can absolutely git checkout the hash of any of the rewritten history and it’s still there, same as you left it. You can even move the branch pointer back, undoing the history rewrite.
- stonemetal12 4y agoSo when I do a pull I get their un-rewritten history? Just because they have a short undo buffer doesn't make modifiable history immutable.
- pc86 4y ago> once you have to do anything more complicated than just commiting/merging If you really have to do more complicated things with git.. why? I mean that seriously, if your workflow necessitates anything more complicated that committing or merging with any level of regularity, it sounds like you have a bad workflow. Committing and merging should be 99.9% of your activity within git, shouldn't it?
- themulticaster 4y agoIt depends a little on how you use git. Apart from stashing (git-stash), I use interactive rebases a lot. Combined with autosquashing it's a very powerful tool to ensure a somewhat nice history. Of course, this only matters if you care about your history. It feels like there are two camps of git users: One camp squashes every MR/PR together even if it's huge, hasn't heard of git-bisect, creates plenty of merge commits in both directions, and piles unrelated changes into a single commit. The other camp cleanly groups changes into self-contained commits, rebases often resulting in a clean patch-series-style MR/PR, and likes to use git-bisect.
- atq2119 4y agoThis observation about the two camps rings very true. The sad part is that while the second camp is the original user base of Git, at least GitHub basically acts as if they don't exist and only really caters to the first camp.
- pmarreck 4y agoSo, like Nix, basically... ;)
- layer8 4y agoItems 1 and 2 are somewhat misleading. Commits are only immutable in the sense that the same commit hash will (with huge likelihood) always refer to the same commit history. But they are not immutable in the sense that you couldn’t change the history of e.g. a branch. Other VCSs actually offer more immutability than Git here. Branches are sequences of commits only up to the last merge, because they are really just labels on branch tips. In other VCSs, branches are truly linked with each commit of a sequence. Meaning, when you’re familiar with such a VCS, reading items 1 and 2 may lead you to think “well, that’s what I know and expect from a VCS”, whereas really it is a bit different in Git.
- stu2b50 4y ago> But they are not immutable in the sense that you couldn’t change the history of e.g. a branch. That sentence doesn't make sense, though. Assuming from context that `they` = commits, "[commits] are not immutable in the sense you couldn't change the history of a branch" Branches and tags are mutable - they're just pointers to commits - but that doesn't change whether or not commits are immutable. When you "change" the history of a branch, what git is really doing is creating another series of new commits, and then making the branch pointer point to the new commits. However, because commits are immutable, the old commits are still there, and at any time you can go back.
- deleted 4y ago[deleted]
- layer8 4y agoYou are defining commits to be different by the mere fact that their contents (and history) is different. With that definition, how could a commit ever be mutable? Only by an indirection were the VCS allows the referencee to change. And that is exactly what Git allows with branches. When rewriting history, the fact that the “new” commits are new is a tautology if you define commits to be different when their contents is different. This only matters when you use the commit hash as your reference point, which is what I was pointing out in the parent comment. The expectation of immutable commits would be that history never gets lost and cannot be changed (without rewriting history into a different repository), but it certainly can in Git. The real point about Git’s content-derived addressing is that it enables the distributed aspect, because it makes the path a commit has taken between repositories not matter. But that is already better expressed in point 3.