4 ms·
A lot of things in git are just pointers to commits, and then the git implementation handles them under the covers in some way that usually makes sense but not
by zdw 3y ago
A lot of things in git are just pointers to commits, and then the git implementation handles them under the covers in some way that usually makes sense but not always.
One example that also bites people: moving files isn't stored in git - if you move files (even with `git mv`) and create a new commit, the moves aren't stored, but this is reconstructed later by the client based on similarity, which comes from the diff algorithm.
And git has multiple diff algorithms to pick from: https://git-scm.com/docs/git-config#Documentation/git-config.txt-diffalgorithm https://git-scm.com/docs/git-config#Documentation/git-config...
And optionally to not detect renames in diff output with `diff.renames`: https://git-scm.com/docs/git-config#Documentation/git-config.txt-diffrenames https://git-scm.com/docs/git-config#Documentation/git-config...
- keybored 3y agoYup. “Storing moves” is the kind of thing that might sound intuitively obvious but then gets gnarly and non-obvious when you think about it for five minutes. And so something that might be “obvious” to do then turns out to be so non-obvious—how to catch all file moves (intent) outside of simple identitical content cases, and how do you represent them internally?—that you realize that just using snapshots is really the best thing to do.
- hyperthesis 3y agoBitKeeper already did it.
- lubutu 3y agoI think this is the one thing I feel BitKeeper does better than Git. Git can get confused about where a file came from, for moves but especially for copies, and so the version history ends, even if you ask it to try and follow along. BitKeeper, on the other hand, keeps the moves and copies as part of the history, so you can always trace it through to the origin of the file, no matter how circuitous.
- account42 3y agogit log has --follow but unfortunately it only works when spefying a single file and not e.g. a whole directory.
- chrismorgan 3y agoIt’s completely trivial. The obvious and correct place is in the commit object just like author and date and such, since renaming is semantically part of the commit, not the tree: commit 0123456789abcdef0123456789abcdef01234567 parent fedcba9876543210fedcba9876543210fedcba98 author Nemo <nemo@example.invalid> 1234567890 +0000 committer Nemo <nemo@example.invalid> 1234567890 +0000 rename-from path1.old rename-to path1.new rename-from path2.old rename-to path2.new Commit message And you don’t detect moves (because that’s madness), but require that people record them deliberately, just like every other VCS has done. There’s even git-mv already, it just skips a step that every other VCS’s equivalent command would do. (And technically this all works out because the index is a commit, so you can record the rename normally.) Of course, all of this assumes that moving a file is a meaningful operation. Perhaps ideally (for most languages and systems) you’d track this in far smaller chunks, so that you can track changes to a function even when it alone was moved to a different file. But things like Git aren’t interested in those kinds of semantics, and work technically at the file level, more or less, so I think it should track renames because in practice straightforward renames are super common, but often also involve other changes that thwart rename detection. Years ago Linus explained why he didn’t like storing moves (someone else has linked it), but I’m largely not sold with his reasoning—the theory of the perfect has hindered the useful, and file renames are commonly meaningful in ways more than he said.
- silon42 3y agoThe problem with that scenario is that usually it doesn't support a real-world-scenario where you do a rename in the tool (like some IDE) and it doesn't do the corresponding git operation. (yes, some IDE might have git integration, but personally I don't like my IDE messing with git, except read-only (annotate, diff))
- chrismorgan 3y agoThat’s… nothing special. If you don’t have Git integration in your IDE, you already have to do something like `git mv` or a `git add` and `git rm`. Nothing has changed in this new hypothetical world.
- 3y ago
- 2-718-281-828 3y ago> moving files isn't stored in git is there an intuitive and enlightening explanation as to why it is this way?
- keybored 3y agoGit stores snapshots and that’s it. The whole tree, not per-file. As to why Linus doesn’t like storing file moves: https://public-inbox.org/git/Pine.LNX.4.58.0504150753440.7211@ppc970.osdl.org/ https://public-inbox.org/git/Pine.LNX.4.58.0504150753440.721...
- bqmjjx0kac 3y agoMan, he communicates like a dick all the time I guess.
- keybored 3y agoHe does argue in a borderline hysterical way on many occasions.
- xorcist 3y agoI'd be happy to argue why Linus is wrong here. Many things would be much easier if git recorded some more metadata in every commit: file moves, and branch moves, to start with. Having some sort of notion of "parent branch" would be very useful for a number of common operations, and a "renamed file" without having to rely on client dependent heuristics too. Empty files trip people up all the time so a "create file" would fit in perfectly. These concepts would also be a good basis for more user friendly clients. Other version control systems do this the surprise factor should be low.
- erik_seaberg 3y agoPeople would get lazy and rename a file without telling Subversion they had done it, so it would write a “old file deleted, new file created from nothing” revision. Most of the merge conflict resolution machinery just couldn’t run without the missing guidance. Git infers someone probably renamed a file you edited or vice versa, which seems risky but works better in practice.
- smusamashah 3y agoMy TL;DR; for git commits is that these are connected like a linked list but in reverse and has more pointers than just head/tail. I recommend having a look at Merkle trees. I don't understand git cli, but I can manipulate git commits, branches, tags etc well based on basic understanding using a good git UI.
- deleted 3y ago[deleted]
- Izkata 3y agoThis has resulted in a feature not in VCSs that do track renames: using matching lines, git blame can track changes across files that were combined in a commit, where others would record half the lines as being a rename from one file and the other half as new lines (if you even thought to do it like that when making the commit; more likely the whole file would be tracked as new).