7 ms·
I understand how git works, and I still can't use it. There are three problems: 1. Despite the claim that git never loses data, there are actually some dange
by lisper 5y ago
I understand how git works, and I still can't use it. There are three problems:
1. Despite the claim that git never loses data, there are actually some dangerous operations that will irretrievably nuke your work with no warning. Git checkout is the canonical example. This makes me very gun-shy about doing anything that I'm not intimately familiar with.
2. Git's merge is not smart enough to realize that identical changes in two branches are not actually a conflict. I've often ended up in situations where a small bug has been fixed in two branches which then won't merge without manual intervention. This is incredibly annoying. (To be fair, this is not unique to git. But because git encourages branching more than other systems, I encounter it more when using git in idiomatic ways.)
3. This is the biggie: translating the abstract idea of what I want to do into an actual git command is a black art. The underlying model is beautiful, but the UI is atrocious. The plumbing is great. The porcelain is cracked and mildewy. There are mysterious valves and pipes all over the place when all I want is one control for the hot water and another one for the cold.
- grogenaut 5y agothe recommendation is actually used a different algorithm for the language that you're working in so I just use beyond compare and 99% of my simple conflicts or Auto resolved. It'd be better if these algorithms were just built into the sea Alli itself but they decided in unix style to delegate
- arxanas 5y agoThere is a design for undoing changes to the staging area: https://github.com/arxanas/git-branchless/issues/10 https://github.com/arxanas/git-branchless/issues/10 The similar project [Jujube](https://github.com/martinvonz/jj https://github.com/martinvonz/jj) has experimented with backing up even unstaged changes after every command, and apparently it works well for them, so we could do the same in the above design. Undoing even untracked changes might be a bit much.
- lisper 5y agoYeah, this barely scratches the surface though. Take branching, which is something you're supposed to be doing all the time. So abstractly, I want to be able to get a list of my current branches, create a new branch, check out an existing branch, delete an existing branch, and maybe rename a branch. I would expect the commands for these operations to be something like: git branch list git branch create [name] git branch delete [name] git branch rename [old-name] [new-name] We can argue over whether checking out a branch should be "git branch checkout [name]" or just "git checkout [name]", but in either case, if I have unsaved changes in my working directory, I would expect to at least get a warning about this before that work got clobbered. None of these things are actually the case. Git checkout will clobber unsaved changes in my working directory. "Git branch list" is just "git branch". "git branch create" is "git branch [name]". So creating a branch is the SAME COMMAND as the one you use to produce a list of current branches, just with an argument. Madness. And this is the rule, not the exception. Minor variations on a theme can result in radically different commands with various mysterious arguments. There is no rhyme or reason or regularity. The only way to know is to look it up.
- akersten 5y ago> Git branch list" is just "git branch". "git branch create" is "git branch [name]". So creating a branch is the SAME COMMAND as the one you use to produce a list of current branches, just with an argument. Madness. And this is the rule, not the exception. As a counter-opinion, I actually like it this way. Especially since it's the rule and not the exception. When one makes the small effort to learn the commands, the payoff in saved keystrokes from avoiding typing the redundant pieces is great. As a painfully simplified justification: Directory listing is "ls" and removing a directory is "rmdir" - I much prefer that to typing a hypothetical "directory list" and "directory delete", even if the later fits some nice consistent shape. It's one of the reasons I hate powershell/windows-style CLI and its 60-character long arguments for every function.
- lisper 5y agoThere's nothing wrong with having a UI for power users in addition to a more intuitive one. But having a power-user UI as the only option (or even as the default) is not so good.
- atoav 5y agoI really would wish git would embrace the idea of not destroying any data unless specifically prompting for it first. Same for merging pull requests. How hard would it be to again prompt in case of conflict how to proceed?
- cerved 5y agoCommits are immutable, itś incredibly hard to destroy data that has been committed. Even if they become loose objects, Git is very conservative when it comes to deleted that. If you have uncommitted data, git will refuse to do lots of operations. The default is always to not delete changes, even if resetting a branch. Contrast that with TFVC which tries its best to nuke everything within it's reach (that is not under version control) in inexplicably stupid ways. tf reconcile . -r -clean This command is equivalent to git reset --hard origin/head && git clean -fdx Because that's sensible. tf reconcile . -r -i clean One might think -i is a short flag for -ignore. No. It's short for -preview. That's a "feature". Good luck finding the documentation for this idiotic behavior. How about if you pipe a list of files into tf reconcile, to avoid it's idiotic behavior? Say git ls-tree HEAD -z | xargs -0 tf reconcile -r -clean You better hope that ls-tree outputs something, otherwise that is the same as calling rm -rf . I can't say I recognize your experience. You only risk creating a mess of changes to the point where it's hard to recover due to the share amount data it hasn't deleted.
- dorian-marchal 5y agoUnfortunately, it is still very easy to lose data, e.g. by trying to undo a temporary commit with `git reset --hard HEAD^` (note the --hard option) before committing your changes.
- AlexSW 5y agoAgreed. I consider myself pretty competent at git (consistently helping out the rest of my team of ~15 people with it) and even then I've shot myself in the foot using `git checkout --` instead of `git reset` before to unstage a file, and lost all of my work on it. Really felt that should have given a warning.
- IshKebab 5y ago> The underlying model is beautiful, but the UI is atrocious. I definitely agree. The UI is terrible. But it is learnable. I would recommend using a GUI initially so you can learn what the operations are and do without having to figure out that it's not `git remote list` it's `git remote -v`; it's not `git clean` it's `git checkout . && git clean -fdx` and a million other paper cuts.
- MereInterest 5y ago> that identical changes in two branches are not actually a conflict I think this is part of a downside of rebase-centric workflows, since it encourages making multiple branches with identical changes, but no shared history. At some point I want to read more pros/cons on different workflows. My current thinking is that rebase-only sacrifices far too much on the altar of a clean-but-inaccurate commit history, but I don't yet know enough to say for certain.
- lanstin 5y agoI think if you run into this a lot, git revere will be helpful: https://www.git-scm.com/book/en/v2/Git-Tools-Rerere https://www.git-scm.com/book/en/v2/Git-Tools-Rerere If you have a lot of long-lived branches that don't merge and get deleted you have a whole different world of pain from normal git usage, and need some resources designed as SCM experts to manage this stuff. But really short lived branches that deliver net steps forward are the way to live. I hate branches because it breaks git-bisect. Linux kernel history has lived without it, so I'm guessing the "our code is so complex we need it" is a false idea. Also, the actual history of what main/master points to is linear. If the bit-post merge are identical, it doesn't matter if they were rebased or not except having 2 ancestors for HEAD is a lie.
- MereInterest 5y agoOoh, rerere looks really nice. I have a few cases where I've needed to repeatedly rebase long-lived branches. (Feature branch A depends on feature branch B, but some small aspects of feature branch B are still under discussion. Feature branch B needs to be occasionally rebased onto main to avoid conflicts, after which branch A needs to be rebased onto B again.). Something that I try to avoid, but that sometimes happens anyways. Can you explain what you mean by git merge breaking bisect? I've never run into that problem at all. And sure, it might bounce between the branches as you bisect, it still identifies the commit that introduced a bug. The only issue is if one of the commits on the branch fails to compile/test, which is poor commit hygiene, but can be excluded from the bisect. I still need to do more research, but I think I'd lean toward having a merge workflow, but with no fast-forward commits. That leaves a clean history on main with --first-parent, but still leaves the details available in the branches as needed.
- alex_smart 5y ago>The plumbing is great. The porcelain is cracked and mildewy. You might enjoy using Magit.
- marton78 5y agoI would if I used Emacs
- pja 5y agoPlenty of people run Emacs purely in order to use Magit & don’t use it for anything else. That’s how good Magit is.
- lanstin 5y agoIt is excellent, and you can use it well without reading anything (assuming you know git, and I know emacs so maybe that too, although it has the pleasant property of listing a lot of keyboard commands in the UI).
- lmm 5y ago> 2. Git's merge is not smart enough to realize that identical changes in two branches are not actually a conflict. I've often ended up in situations where a small bug has been fixed in two branches which then won't merge without manual intervention. This is incredibly annoying. (To be fair, this is not unique to git. But because git encourages branching more than other systems, I encounter it more when using git in idiomatic ways.) I agree with your other criticisms, but IME git's branching-heavy approach makes this one easier to avoid: it's natural and easy to create a separate branch for that bugfix and then merge it everywhere that it's wanted. Or to just merge your colleague's feature branch that has the fix on into your own feature branch, if you know their branch doesn't contain any dangerous changes / will hit master ahead of yours. (If the diff is actually bit-for-bit identical I think it doesn't conflict? But obviously that doesn't happen so much in practice. git merge -Xignore-all-space can be helpful in some cases).
- lisper 5y agoYes, but to make that work you must do it for every change you want to make, even the most trivial. Find a typo while you're working on something else? You can't just fix it. You have to branch, edit, cherry pick, commit, and then push to make sure someone else doesn't find and fix the same typo. It's damned annoying because it would be so simple to fix: just tweak the diff algorithm to check if the conflicts are identical and auto-merge them if they are. How hard can that be?
- lmm 5y agoThere shouldn't be a cherry pick involved, and my protip would be that you don't actually need to make a local branch for small changes; quite often I'll just do `git checkout origin/master`, make the fix, commit, and `git push mine HEAD:refs/heads/quickfix`. But yeah, it would be nice to have a way to just commit a diff at a different point in history without having to check it out.
- lisper 5y ago> There shouldn't be a cherry pick involved There is if you discover the typo in the middle of working on something else, which is usually the case for me.