9 ms·
Sadly the inconsistent and baroque command line interface of git for basic stuff is the least of its problems -- learning it is just a one time sunk cost every
by patrec 6y ago
Sadly the inconsistent and baroque command line interface of git for basic stuff is the least of its problems -- learning it is just a one time sunk cost every developer has to pay these days.
What's more troubling is that git can't do some very basic stuff well, like merging branches. I mean you can do the merge, but good luck trying to revert it[+] or trying to get git to deal intelligently with non-linear history in general.
Another fun thing is that every git repo starts its life with an off-by-one error: there is no canonical (and identical) first "root" commit, a NIL commit if you will. This is unfortunate for two reasons:
1. A lot of common scripting idioms will break on the first actual commit (e.g. finding changed files via git diff --name-only A A^ will not work if A is the first commit; yes it's possible to work around that, just like you can write shell scripts that deal with filenames with spaces). Also, it would be convenient in many cases to have an canonical initial empty NIL commit as symbolic reference, similar to how having HEAD is handy.
2. More subtle: the fact that there is no common shared root commit between arbitrary repos makes a couple of things more involved and confusing than they would otherwise be, for example rewriting several different repos into one after the fact.
In theory it would be possible to work around that by everyone agreeing on a canonical first commit to start each repo with, but in practice that's of course unlikely to happen.
Lastly, and not entirely unrelated: many, but no good solutions for sub-repositories.
[+] https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt https://github.com/git/git/blob/master/Documentation/howto/r...
- tcoff91 6y agoWhat VCS does a significantly better job on branch merges? All the other ones that I've experienced were horrifying. Merging subversion branches was a nightmare compared to git. Perforce was better than subversion but still pretty bad compared to git. I've also reverted merges many times in git with no issue. You just choose which parent you're reverting to and then it just works. The only time I've seen branch merges in git really fuck up is one time when a novice git user at my company unstaged a file from the index before committing the merge. That was a disaster and took me hours to figure out what the hell was going on with that file.
- patrec 6y agoThe problem with reverts of merge commits in git is that it doesn't behave like most people intuitively expect. If you merge B into master, find a problem, revert the merge and push a fix to B and try merging B again most devs would expect the result in master to be equal to having just merged the fixed version of B to begin with. But it ain't so. I agree of course that SVN is much worse than git for most purposes, although it's still used frequently in preference to git in design artifact heavy settings because it won't choke as quickly as git on binary assets from artists or designers. The question of what tool handles merge commits better is a bit academic to me, so I do not know the answer. The two reasons for this are: 1. there is currently no practical benefit in learning a better VCS given the dominance of git 2. I gave up on using merge with git.
- lmm 6y ago> What's more troubling is that git can't do some very basic stuff well, like merging branches. I mean you can do the merge, but good luck trying to revert it[+] or trying to get git to deal intelligently with non-linear history in general. IME Git handles non-linear history pretty well. AFAICT any DVCS will inherently have the same problem; you can't necessarily memory-hole the fact that the merge has happened because other people may already have your merge. What are you claiming is the "right" way to handle that case? > In theory it would be possible to work around that by everyone agreeing on a canonical first commit to start each repo with, but in practice that's of course unlikely to happen. I believe there is a known commit hash that's there in the datamodel. So it would be possible to treat this as NIL with just changes an the UI level. I agree it's a deficiency, though I don't think it's the most important problem with git (the huge inconsistencies around the staging area are much more important IMO). > Lastly, and not entirely unrelated: many, but no good solutions for sub-repositories. I don't think a good solution is possible, personally. The repository is the unit of history, branching, tagging and so on, and that makes for a nice model that I don't want to change. If you have multiple repositories, it's better to deal with them as such.
- patrec 6y agoThe issue is not one of memory holing: non-merge commit reverts work as people expect (and leave a historical record). I think the right way handle this in git, in most cases, is to just avoid merging altogether. Do work on feature branches and rebase those into master (possibly adding some meta-info like Feature: 123 to the individual commits as you do the rebase). Apart from not having to explain the semantics of merge reverts to everyone in your team this saves a lot of other conceptual overhead as well. I disagree that git deals well with non linear history, everything about dealing with non-linear history in git is pretty painful, from bisecting to querying (compare to revsets in mercurial, for example) or logging. Multiple independent repositories across a single org (working on one product) don't work well, in my experience. Unless your org is large enough to hit scalability problems monorepo seems the way to go with git -- it makes it easy for everyone to find stuff and use a consistent shared "timeline". However, other than submodules and co in git being a tire fire, I see no reason why the same purpose could not be served by subrepos in many cases; what makes you think they are inherently problematic?
- andreareina 6y agoThe commit hashes will be different, but I always start a fresh repo with `git commit --allow-empty -m "initial commit"`
- patrec 6y agoWhy not got the whole mile, and do something like this: GIT_AUTHOR_NAME='nil' GIT_AUTHOR_EMAIL='nil@example.com' \ GIT_COMMITTER_NAME='nil' GIT_COMMITTER_EMAIL='nil@example.com' \ GIT_AUTHOR_DATE='1970-01-01 00:00:01' GIT_COMMITTER_DATE='1970-01-01 00:00:01' \ git commit --no-gpg-sign --allow-empty -m 'NIL' This will give you an identical commit hash every time. [Edit: added --no-gpg-sign as suggested in reply below]
- deleted 6y ago[deleted]
- JNRowe 6y agoYou can ensure the hashes are consistent by setting GIT_AUTHOR_DATE and GIT_COMMITTER_DATE in your initial commit alias. They still won't be consistent if you've enabled commit.gpgSign though. So, you'd want --no-gpg-sign on that initial commit or someone to reply with a better idea.
- patrec 6y agoThanks, incorporated your --no-gpg-sign suggestion. I think it's best to use a canonical author/committer as well. Ideally everyone would agree on something so tooling like commit linters (which check org email addresses or commit message formatting) can ignore it and different repos across at least a single org benefit from having the same root commit.
- JNRowe 6y agoThe other benefit to your full solution is that you won't get a 50 year sidebar in your GitHub contribution profile too. Until seeing your suggestion it hadn't occurred to me to use a fake user. However, using UNIX epoch was something I had been doing and I do have the 50 year sidebar ;) https://github.com/JNRowe#year-list-container https://github.com/JNRowe#year-list-container
- scrollaway 6y agoI always initialize my repos with git commit --allow-empty -m "Initial commit", for that exact reason. I agree with you that git should provide a root commit on init.
- patrec 6y agoSee my reply to sibling on how to do it in a reproducible fashion. Maybe we should just all agree on a canoncial initial commit after all? :)
- scrollaway 6y agoI don't think there's a real point to do this "in a standardized way"; imo we should just push for git initializing its own empty initial commit.
- patrec 6y agoI agree git init should do it, but a) it still needs to be the same commit every time to work properly b) a particular "canonical" standard initial commit becoming a defacto standard in the wild presumably increases the chances that this makes it into git itself.
- bmn__ 6y ago> by everyone agreeing on a canonical first commit Make git-insert-empty-root a standard. https://stackoverflow.com/a/14729121 https://stackoverflow.com/a/14729121
- deleted 6y ago[deleted]
- divbzero 6y agoNot a full solution to the no-common-root challenge but rebase [1] does provide the option to: git rebase -i --root [1]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---root https://git-scm.com/docs/git-rebase#Documentation/git-rebase...