[HN Gopher] Git undo: We can do better ___________________________________________________________________ Git undo: We can do better Author : arxanas Score : 507 points Date : 2021-06-21 14:49 UTC (8 hours ago) (HTM) web link (blog.waleedkhan.name) (TXT) w3m dump (blog.waleedkhan.name) | vzaliva wrote: | May I have it in Magit, please? | snackematician wrote: | Magit's wip-mode seems similar in some respects: | https://magit.vc/manual/magit/Wip-Modes.html | | I haven't tried it, but have been meaning to look into it. | Would be curious to hear experiences of anyone who's tried it, | and how it compares to the OP. | kbd wrote: | I'll often launch lazygit just to use its undo feature since | that's easier than navigating the reflog. Happy to see a | standalone utility. | jldugger wrote: | `git-undo` has been part of git-extras[1] for a while. It doesn't | use fancy git magic, so maybe this is better. | | [1]: https://github.com/tj/git-extras | skrebbel wrote: | It only removes the last commit. It's terribly named IMO, | actually, cause I think that's seldomly the kind of thing you | get into "omg I messed up how do I undo" panic for. | | The undo described here is much more powerful and much closer | to what people expect from the word "undo" from its | functionality in other tools. | professoretc wrote: | From the article: | | > How is it so easy to "lose" your data in a system that's | supposed to never lose your data? | | I think the author is mistaken; git isn't "a system that's | supposed to never lose your data". One of its _features_ is the | ability to "lose" data in a controlled way; i.e., to rewrite | history. If you want a version control that is supposed to never | lose data, use Fossil. | arxanas wrote: | This is a figurative use of the word "lose", hence the quotes. | The beginner comes in with the impression that it's impossible | to lose your data with Git, and then manages to "lose" it | anyways. Whether it's really lost, or it's just that the user | doesn't know how to get it back, isn't relevant from the | novice's point of view. | gpanders wrote: | Even if you rewrite history, the data is not lost. The old | commits are still in the reflog and can be recovered. | | It's extremely difficult to lose anything in Git once it's been | committed. You'd have to do something pathological or | intentional. | urxvtcd wrote: | It's also possible (if difficult) to recover files which have | been git-added and not commited. The only files git can't | recover are the ones that it hasn't registered in the first | place. | pjettter wrote: | Git should store the commands that "did" the operations on a | repo. Git should never ever let you lose work. I should always be | able to go "backward" and recover previous states. I guess that | is what the "Git undo" proposal is about. | | I'm a very visual person so I tend to use Git Graph on VSCode. | But I still get in trouble. Especially things like Cherry | Picking, or reverting. | | Another thing that is not so easy is switching branches without | having to do a commit. Stashing, yeah, but then figuring out | whether stashes have been applied or not, diffing between | branches, picking some changes from a diff. | | In the end I stick to some basic commands that don't get me in | trouble so that I don't lose half a day to recover my work via | Dropbox. | prisonality wrote: | > Git should store the commands that "did" the operations on a | repo. | | is `git reflog` not enough for your use case ? | pjettter wrote: | No, I mean more like an audit trail. Not like `blame` either. | What I typed on the command line to get into a new state. | sixstringtheory wrote: | What about `history | grep "^git"? | | Edit to add: the downside is that it only works in the | current terminal session. To workaround that for myself, I | have a fish shell post exec function that records the last | command run, plus a bunch of metadata, to a log file. | whiddershins wrote: | I don't understand. You can always restore any previous state | using git, I used to do it from the command line. | | If I use github desktop I can roll back a commit whenever I like | with a simple menu command. | | What am I missing here. I feel like I don't understand what the | tool is doing. | nerdponx wrote: | https://github.com/arxanas/git-branchless/wiki/Architecture#... | whalesalad wrote: | If you understand the fundamentals of a version control system | I find git relatively intuitive to use. Sometimes I don't know | the exact cli syntax for a complicated procedure but that's | easy enough to figure out if you know the concepts. Most people | fail to learn the concepts and then try to brute force | everything. | jonahx wrote: | The README for the parent repo (https://github.com/arxanas/git- | branchless) answers these questions in detail. | | Short answer, recreating this tool's features in vanilla git | requires using the reflog, which isn't user-friendly: | | > Why not git reflog? | | > git reflog is a tool to view the previous position of a | single reference (like HEAD), which can be used to undo | operations. But since it only tracks the position of a single | reference, complicated operations like rebases can be tedious | to reverse-engineer. git undo operates at a higher level of | abstraction: the entire state of your repository. | deknos wrote: | i wish the branchless tools would be incorporated in standard | git. :| | vgaldikas wrote: | Shouldn't the article be called "We can undo better" :D | globular-toast wrote: | > Here's my theory: novice and intermediate users would | significantly improve their understanding and efficacy with Git | if they weren't afraid of making mistakes. | | Agreed. When I was learning to climb the instructor told me I | would never reach my full potential until after the first fall. | You cannot work at your limit until you trust the rope. | | However, I think this is still avoiding the rope. Git is really | simple and when you understand it it's hard to go wrong. I really | think what git is missing is a better user interface. Magit is | the only one I'm aware of. | chalst wrote: | The easiest way to make mistakes cheap is to have your working | directory on a filesystem with automatic snapshots, such as | nilfs. | chagaif wrote: | I'm still scared of using got undo | max_hammer wrote: | How hard is | | `git reflog` `git reset --hard <SHA of commit you want >` | | Or if you just want to move back 1 commit | | `git reset HEAD@{1}` | leifg wrote: | git reflog is hard enough so that I (a software engineer for 12 | years and a git user for 10+ years) have to look up its syntax | every time I need it. | mattkrause wrote: | I invariably parse reflog as "re-flog." I know isn't the | intended meaning but does capture the feeling of needing to | use it quite nicely. | SamBam wrote: | Can you explain what's tricky about it? For me, I just had to | remember that "reflog" was the name for "history." | | Once I did that, everything else is just regular git | commands. Check out a "commit." Revert to a "commit." | amelius wrote: | I think this is the problem with any command which you only | need once in a blue moon. | | I always forget how to set up networking, because I don't do | it often enough. | juped wrote: | Weird, it has no syntax... | thewebcount wrote: | I'm not sure what you mean. Typing "git help reflog" brings | up a man page that lists commands like "show", "expire", | "delete", etc., each with additional options. | awb wrote: | I say code in my head when I'm thinking through how to approach | something. Neither of those code snippets are smooth to recite | for something that's a fairly common operation. | [deleted] | shadowgovt wrote: | I don't think the issue is so much that it's "hard" as that | it's "not undo." | | As a general rule of thumb, command line tools often ignore | decades of UX best practice that have grown up. One of those is | that operations (particularly destructive ones) should be | easily reversible. It recognizes that human error is common. | | And having "undo" specifically recognizes that human error puts | the user in an emotional state where restoring things via | complex operations is inviting risk. A typo to `git undo` is | unlikely to be another command. A typo in the SHA (or an @{2} | instead of an @{1}) for `git reset` will compound the error. | | ... that having been said, I'm going to go add `git undo` as an | alias for `git reset HEAD@{1}` right now. | sicromoft wrote: | I know right? And a monad is just a monoid in the category of | endofunctors. What's the problem? | [deleted] | arxanas wrote: | Sometimes, it's really hard. Using the reflog is like looking | through a pinhole. | | When recovering from a bad merge conflict, you have a bunch of | commits in your reflog which have the same name, and you need | to decide which one you want. It's hard to look at the exact | diff data and decide which one is appropriate. | | It's not listed in the article, but it also enables a workflow | where you check out parent commits many times along your branch | of development and start new offshoots, and possibly amend | commits with many descendants. It becomes nigh impossible to | manage the reflog when there are so many commits with the same | message but different content. The reflog itself also doesn't | make it easy to recover lost descendant commits, only the given | root commit. | | Other scenarios: the reflog will not help recover where a | deleted branch pointed to, and it won't help update multiple | branches that pointed to the different positions in the same | rebased stack of commits (the reflog for HEAD, anyways). | happytoexplain wrote: | The complexity of executing a solution is irrelevant to the | complexity of determining a solution. Regardless, you're being | dismissive, and that attitude contributes to the unwillingness | of people to ask questions, and therefore hinders learning on a | large scale. | sedatk wrote: | I think Mercurial is way ahead of Git on this department by | having repositories immutable by default, so even undo actions | would have their commit. You never find yourself in an | unrecoverable situation. Advanced mutable features can only be | accessed by making configuration changes, and are still safe to | use because public changesets are differentiated from draft | changesets, so, you can only make changes on your own work, not | anything else. I mean, you can force it, but that comes with its | warnings. | | Mercurial has no staging area, and that can be inconvenient for | some scenarios; but I think no-staging model is easier to grasp | for beginners. I especially think many beginners would assume | that modifying a file after it's been added to staging area would | update staging area automatically too. | | Mercurial has high-level, scenario-oriented distinct "undo" | commands like "revert", "forget" and "backout" instead of | overloading a single command ("reset") for everything. | | I still like `git reflog` though. | globular-toast wrote: | Git is immutable. The only thing that isn't is your working | directory. | umvi wrote: | Sounds like mercurial repos would have a lot of "noise" with | that approach - commits for fixing other commits spamming | everywhere | capitainenemo wrote: | https://www.mercurial-scm.org/doc/evolution/user- | guide.html#... | | The key thing seems to be the immutable repo editing is | hidden by default, but viewable with --hidden flag if you | need it. | jonathanberger wrote: | Git is one of those bizarre products that has remained a leader | in its category for almost a decade while being extremely | difficult to use, even for experts. Another one of these products | is Apache. | | Why is this? | | At least from my naive point of view I would expect these | extremely user-hostile products to have been overtaken but more | user-friendly alternatives. I know the best products don't always | win, but when they don't there's often at least some theory about | what is going on (network effects, business partnership, | government regulation, etc.) that I don't have with these two | products. | secondcoming wrote: | Apache is popular because writing a fully spec compliant HTTP | server is actually quite difficult. We use it, I don't like it, | but I have enough experience with HTTP to know to not write my | own implementation, especially in C/C++. | MetaWhirledPeas wrote: | It has remained popular because it feels like the correct | approach in almost every situation, despite having a difficult, | obtuse UI. After spending years with Microsoft's centralized | version control and then switching to Git it's like a breath of | fresh air. | | Granted, I almost never use the Git command line and always | favor a 3rd party GUI. For users who are a tad confused I think | this is the right approach. And to me that's what makes Git a | winner: the core software is powerful enough to do everything | that needs to be done, and you can pick whatever UI you're | comfortable with. No one is forcing you to use Git's built-in | UI. | | That said I think even the high-level Git concepts have naming | that confuses new users. "Pull request" annoyed me for a long | time. Yes I _technically_ understood why they chose that term, | but practically speaking it just seemed pointlessly misleading. | leotaku wrote: | I would guess that network effects and the amount of quality | tools built on top of Git are the main reason for its | prevalence. | | Fossil and Darcs sure look nice, but having to self-host my | repositories or use a smaller company that could go under at | any minute? Having to use barely-maintained plugins for my | editor, CI, CD, etc.? And most importantly, having to explain a | completely new set of tools to anyone who wants to work on my | projects? In my opinion, it just isn't worth it. | cratermoon wrote: | It's almost impossible to really lose anything once it's | committed to git. Just look at the efforts it takes to really | remove accidentally committed secrets. | | The hard part is understanding how to get a reference to the | thing you want to get back, how to restore it to its proper place | in the history, or at least to a reasonable place, and how, if | it's been pushed to a shared repo, for other developers to get | their local clone properly sync'd up without their local work | getting shoved off into some hard-to-reach reference. | rglover wrote: | Calling attention to this which has an undo command and has been | very helpful for Git tasks: https://github.com/tj/git-extras | Jakobeha wrote: | Any other recommendations for CLI tools? | | I've gotten kind of familiar with the Git CLI. But it took a lot | of wasted hours and headaches to do so, and even now it takes | headaches and extra time / effort to do certain things like | rewrite history and "good" commits. I still prefer CLI to GUI but | I wish it was more intuitive. | jph wrote: | Git Alias has many: https://github.com/gitalias/gitalias | jgilias wrote: | There's tig: https://jonas.github.io/tig/ | | It doesn't have too many features, but the main thing it aims | for - a better repo browser, it does really well in my opinion. | qq4 wrote: | I can second tig, it really helps me parse the repo. | arxanas wrote: | You should check out the rest of the git-branchless suite | mentioned in the article: https://github.com/arxanas/git- | branchless. `git restack` is really useful for some of the | rewrite cases. There are some other improvements to rewriting | in the devel branch. | eric4smith wrote: | Damn, this is such a GREAT idea. I've messed up repos a few | times, and it's never good. It's always -- "what's the magic want | I have to wave now"? | | The truth is, while we use git every day, most people really | don't understand how it works. | | There I said it. And I'm not ashamed. | | I don't really know how Git works. And I think I'm not the only | one. | | What does "git reflog" or "git reset --hard ...." do? What are | the implications? | | We don't really know. | | I feel stupid. But hey, at least I'm honest. | eric4smith wrote: | I do use git every single day. It's a super valuable tool. | Maybe my bad on not taking a course or reading the manual from | cover to cover. | reacharavindh wrote: | +1. | | I wonder if it is possible for someone to write a meta-CLI that | works on top of git like "git for humans". While, still leaving | the power for expert users | jdmichal wrote: | All my git training starts with a whiteboard and drawing out a | commit tree and branch pointers. I only talk about the commands | in reference to the drawings, not the other way around. Most | commands are manipulating this commit tree, so it gives a | visual to latch understanding onto. | | `git reflog` shows the commits where your current branch | pointer has been. | | `git reset --hard` moves your current branch pointer and to the | given commit, then modifies your working directory to match | that commit. `--soft` moves the branch pointer and does not | modify your working directory. `--mixed` moves the branch | pointer, does not modify your working directory, but does clear | staging. | thatguy0900 wrote: | You're not the only one. https://xkcd.com/1597/ | pulse7 wrote: | ...plus git operation names are a bit confusing (pull vs. | fetch, etc.) | lisper wrote: | 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. | MereInterest wrote: | > 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 wrote: | I think if you run into this a lot, git revere will be | helpful: | | 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 wrote: | Ooh, 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. | Shacklz wrote: | > Linux kernel history has lived without it, so I'm | guessing the "our code is so complex we need it" is a | false idea. | | Those guys are still sending commits (patches) to each | other by mail, I think they willingly live in such a | special and weird bubble that it just can't be compared | to any "real life industry project". | | We've recently started to enforce linear history on our | main branches at work, because it makes analyzing broken | builds such a breeze. The mantra is "Insertion is hard, | analyzing/understanding is easy" (for a merge-based | history, it's pretty much the other way around), and so | far it's quite the success. | | It did take quite a bit of effort though to get everyone | up to speed, and it still requires the occasional help to | clean up the commit history of some merge request, but it | was well-worth the trouble so far. | atoav wrote: | I 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 wrote: | Commits are immutable, its 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 wrote: | Unfortunately, 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 wrote: | Agreed. 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. | cerved wrote: | use git stash instead to unstage changes not committed to | the index and you'll never lose anything ever again | unknown_error wrote: | The point is that you shouldn't have to learn everything | by brutal trial and error, losing hours of work each time | you try to learn a new operation and make a small | mistake. | | It's the same reason consumer operating systems have a | trash can and undo features. Just railing on people with | "you should've known better" doesn't really help. | cerved wrote: | That's why it's a flag. You could do git reset HEAD^ && | git stash instead | | Also, git reset ---hard HEAD^ deletes nothing. The commit | HEAD was pointing is not deleted. You have to work really | hard to delete that commit accidentally | glandium wrote: | It does delete whatever uncommitted changes you had. | grogenaut wrote: | the 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 wrote: | There is a design for undoing changes to the staging area: | https://github.com/arxanas/git-branchless/issues/10 | | The similar project | [Jujube](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 wrote: | Yeah, 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. | atoav wrote: | Checkout should be _load_ or _open_. | akersten wrote: | > 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 wrote: | There'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. | seoaeu wrote: | In particularly well designed UIs, the interface for | power users and the intuitive one are one and the same! | munificent wrote: | _> "git branch create" is "git branch [name]"._ | | I've been using Git professionally for of a decade and | you just taught me something new. I always use `git | checkout -b [name]` (which is a completely bananas UX, | but it's the one I know). | seoaeu wrote: | The two commands aren't actually equivalent, because of | course they're not. Usually when you create a new branch | you'd like to switch to it, but _git branch [name]_ | actually doesn 't do that, so you have to execute a | second command after. | IshKebab wrote: | > 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. | jozvolskyef wrote: | Have you tried reading the manual[1]? I read it cover to cover | once and it is invaluable because it gives you the ability to | understand and describe what you're trying to achieve. The | solution is always one search away if you know how to ask. | | [1]: | https://mirrors.edge.kernel.org/pub/software/scm/git/docs/us... | sngz wrote: | this is why i was so sad when mercurial support ended. I loved | using mercurial it just works and it was so intuitive. My firm | last year switched all projects over to github and it's been a | pain, I learned it no problem but still have to google the | occasional thing, but I spend most of my time fixing other | people messing up the repo. | sebmellen wrote: | For some reason people love to defend the obscure and strange | and oftentimes objectively terrible Git CLI. I've found | Mercurial much more straightforward for my (mundane and boring | but prevalent) use cases, and I lament that it isn't more | widely used. | zibzab wrote: | Every single time we are discussing git this comment shows | up. | | But why is one popular when the other one is so much better? | I guess we will never know | _ph_ wrote: | There are several reasons. In the beginning, hg was | critisized to be slow as it was written completely in | python. The effect of the Linux team going with Git instead | created a lot of attention to git, probably also a lot in | people who were faszinated by the capabilities of git and | did not care much about user friendlyness. The biggest push | for git undoubtedly came from github. That is now the | premier platform for hosting software, especially open | source software. | lanstin wrote: | This also shows that quality of the technology matters. | Like the discussion on the business value of Amazon's "use | APIs always," using git is using a superior source code | technology, designed from the ground up for distributed | development by a master of distributed development; good | things are enabled automatically. Linus' naming and UX | choices and inconsistencies aside, the tool is awesome. | That's why it wins in distributed development environments | - the bazaar not the cathedral and not the bespoke | engineering team hidden away in the corporation. | ryandrake wrote: | Although it sounds like a silly reason, compare the names | themselves. I don't even know how to pronounce "mercurial" | without looking it up. The word doesn't exactly roll off | the tongue like git does. And then the command itself is | "hg". WTF is up with that? I mean, ha-ha we all get the | joke, but was the program made for chemists? Unnecessarily | clever. Don't underestimate the extent to which a | difficult/confusing name/brand can harm adoption. | j605 wrote: | I think for most people, they would encounter it in a | science class early in life (at least for English | speakers). And Hg is just the chemical symbol for | mercury, https://pubchem.ncbi.nlm.nih.gov/element/Mercury | #section=Ide... | zabzonk wrote: | > I don't even know how to pronounce "mercurial" | | But you do know how to pronounce "Unnecessarily"? | marcosdumay wrote: | That is solely because of network effects. Anyone of them | could be the popular one, as could any of the weirder ones | like darcs, even it having technical flaws (mostly fixed by | now). | disgruntledphd2 wrote: | GitHub is the reason. Turns out giving beer to developers | globally is an effective way to get a technology adopted. | zabzonk wrote: | Bitbucket used to provide free (and pretty good) | Mercurial hosting. | oblio wrote: | Bitbucket had a much crappier UI. | zabzonk wrote: | Actually, one of the reasons I preferred hg to git is | that Windows explorer GUI integration back then was far | superior to gits, which was buggy as hell. | ivanbakel wrote: | This doesn't seem relevant to the comment you're replying | to. Bitbucket's web UI sucks, which is why it didn't have | the effect on Mercurial that Github had on git. | | Having used Bitbucket and GitHub, I think GH is much | nicer - both in the sense of basic stuff like page loads | being faster, and in terms of features. And since it's | the main tool that everyone on the development team | spends their time on for communication & collaboration, | those things really matter. | mixmastamyk wrote: | Also, remember to compare the sites ten years ago rather | than today. | zabzonk wrote: | The Torvalds effect. | zibzab wrote: | I know you imply, but this could also be interpreted as | "battle proven" or how about "guaranteed to still work in | 30 years" | grogenaut wrote: | Personally I think it just needs a 3.0 where they completely | rename all the commands so that they're really unified. I | know there was pushback on this in the past | seoaeu wrote: | The thing with command line interfaces is that since the | same interface is used by humans and computer scripts, you | essentially end up with an unversioned API that you can | never make breaking changes to. | symlinkk wrote: | It is versioned. There is git ---version. If your scripts | break with the new version, don't upgrade. | matheusmoreira wrote: | That would be nice but will probably never happen due to | backwards compatibility. Breaking changes in git would be | even worse than the slow switch to Python 3. | lanstin wrote: | Just call the consistent one "ggit" and the inconsistent | one "git." | cerved wrote: | The UX philosophy is radically different. One presupposes | that you understand a lot more of the underlying system. The | other tries to focus on what it is what you want to do, as | opposed to how. | | Mercurial is less intimidating if you don't know much about | internals. But tbh, when I use Mercurial I still find myself | searching which command to do things. As a frequent power | user, I find the Git CLI to be more useable. | SkyPuncher wrote: | > The truth is, while we use git every day, most people really | don't understand how it works. | | I once knew how it worked with moderate level of detail, but I | simply do not need anything advanced for my day-to-day work. | carlosf wrote: | Yeah that's my issue as well. I generally forget anything I | don't use often and git is full of important stuff that you | need infrequently. | lanstin wrote: | It's very simple, it's a graph, and you can reason what | changes you want to make to the graph, and then google for | the commands. Re-writing history is really only reserved | for binary checkins, and that task should be assigned to | whomever checked them in, so you should never need to do a | destructive change. Even credentials checked in should be | rotated so they aren't valid, not re-written. | handrous wrote: | I know (or, at least, _have known_ ) how git works, in the way | most people mean that (the data structures & on-disk layout, | what a commit is, what a tag is, what a branch is, what HEAD | is, staging, et c.). What I can't keep straight is WTF the | commands are actually doing, in that low-level sense, which is | a different thing, and there's approximately a 0% chance I'm | ever going to use more than a tiny fraction of the commands | often enough to remember that information. | anoncake wrote: | Maybe for low-level, somewhat rare tasks the ideal Git | porcelain would be a GUI that just exposes the data model | directly. | skeeter2020 wrote: | YES! you learn the happy-path commands you use all the time | and the handful of "sadder-path" approaches you try when | things go south, but there is a dramatic fall-off in | knowledge and understanding from there that leaves otherwise | clever and confident people feeling stupid and frustrated. | This is not a silver-bullet for productivity but still a very | worthy problem to address that could have meaningful impact | for a lot of people. | Vinnl wrote: | I'm the same, but I think that's... Fine? If I understand | what I want to do in terms of first principles, there's no | harm in searching for the exact incantation if I do that only | once every few months. | | For the rest, there's shell autocomplete and muscle memory. | dheera wrote: | Yes. Especially | | git init --submodule --recursive | | Or is it | | git submodule --init --recursive? | | God I hate this UX so much I usually have a ./fetch- | subrepos.sh that runs a bunch of "git clone" commands. | | And if I push without first pulling, must it always punish me | with a merge commit? Can't I say "oh shit I don't want to do | this, go back and git pull"? | ItsMonkk wrote: | It is for this reason that I have changed my workflow to | always stash first, then pull, then pop the stash and do | the merges locally, then push. | [deleted] | lanstin wrote: | And always diff before stash because sometimes it's just | random shit I wasn't serious about, so I'll re-checkout | that file and then stash the rest. | urxvtcd wrote: | > And if I push without first pulling | | I think I know git well, but you got me confused. I've | never heard of pushes causing merges. Surely you are | talking about pulls, right? | kahmeal wrote: | push causes the error, the resolving pull creates the | merge; the correct resolution has been pointed out as git | pull --rebase but most people don't realize this. | MereInterest wrote: | Maybe somebody who has a habit of using --force when | pushing. A major downside of rebase-centric workflows is | that it teaches you to ignore the safety rails when | pushing, or when deleting branches. | Zarel wrote: | `--force-with-lease` would fix this problem (it needs an | alias). Also, `--force` wouldn't cause a merge commit; it | would overwrite the remote changes. | | The only theory that makes sense is that this person | doesn't know how to `pull --rebase`, but the order of | `push` vs `pull` wouldn't change the presence of merge | commits, so I'm still confused. | jtbayly wrote: | I don't know git well, but I often run into the problem | being discussed. | | If I pull from origin before making my changes, I don't | have to merge, obviously. | | But correct me if I'm wrong: I think that if I don't pull | first, but my changes don't conflict with any part of | what was done by the previous commit(s) I missed, I'll | still have to merge if I touched a file they touched. | | This is a common scenario for me. Correct some typos in | comments for example, and I get forced to figure out how | to merge using vim, which I don't know how to use at all | (being a nano user). I'm sure I could and should switch | to at least using nano by default, but I don't know how | merging really works, either. | | What I really want to do is undo my commit, pull, and | redo my commit. Then I don't have to figure out git | merge. | Zarel wrote: | > I don't know git well, but I often run into the problem | being discussed. | | I do understand the problem being discussed; what I don't | understand is what it has to do with pushing first. You | have the same problem no matter which order you use `git | push` vs `git pull`. | | > I think that if I don't pull first, but my changes | don't conflict with any part of what was done by the | previous commit(s) I missed, I'll still have to merge if | I touched a file they touched. | | Yes, that's true. | | > What I really want to do is undo my commit, pull, and | redo my commit. Then I don't have to figure out git | merge. | | You can do that with `git pull --rebase`, which, as | others have mentioned, you can set as the default | behavior of `git pull` like this: | | https://news.ycombinator.com/item?id=27581416 | MereInterest wrote: | Ooh, --force-with-lease looks like a nice feature, | especially for updating github PRs that aren't yet | merged. I still wouldn't want to use it where anybody | else has a copy of the changes, since that's where you | need a merge commit to avoid breaking somebody else's | repo, but that gives me a safer option than a blind | --force. | pjc50 wrote: | Wait, what? I've probably been using Gerrit too long but | why do you ever need force in a rebase workflow? | MereInterest wrote: | These may be specific to a workflow with git + github, | when using git from the command line, but here are the | cases I've run into where overriding safeties is needed. | | 1. After making a PR, there are conflicts when merging | into main. In a merge-based workflow, I would merge main | into the feature branch, resolve any conflicts, then | push. In a rebase-based workflow, I rebase the branch | onto main, resolve any conflicts, but now I need to push | --force. As some of the other comments have mentioned, | this can be improved with --force-with-lease, but still | isn't the greatest. | | 2. After making a PR, there are some typos that need to | be fixed. Fix these in an interactive rebase, to edit the | same commit that introduced the typos. Also requires | either --force or --force-with-lease. | | 3. When the PR is accepted, the result is rebased on top | of main. My local branch still exists, and must be | deleted. I would prefer to use `git branch -d` to delete | the feature branch, but this rightfully says that the | feature branch hasn't been merged in. I instead need to | use `git branch -D` to forcefully delete it, introducing | a point of human error. (There are some cases where git | can delete the branch safely, which I _think_ occurs | either when the feature branch has only a single commit, | or when the feature branch can be applied on top of main | without a rebase, but I haven 't exactly determined it.) | | #1 and #3 are cases where a safer option cannot be used | due to a rebase-workflow. #2 would exist in either case, | since even in a merge workflow, rebasing of branches | before they are pulled makes sense to do. | handrous wrote: | > And if I push without first pulling, must it always | punish me with a merge commit? Can't I say "oh shit I don't | want to do this, go back and git pull"? | | This is a source of probably 50% of my "ah, fuck, time to | undo..." moments with git, these days. I hate that shit. | Muscle-memory gets ahead of me and I commit on a shared | remote branch, which would be fine given our workflow | except that I didn't pull first. What a pain in the ass. | Nullabillity wrote: | For the sake of your coworkers (and your future self), | please don't lie just to make your history look pretty. | lamontcg wrote: | I guess I have `git pull --rebase` as muscle memory. | | I would guess there's an easy way to make git do this | automatically for you via config so you never forget, but | I just never, ever `git pull` | | Or: | | > git config --global alias.up '!git fetch && git rebase | --autostash FETCH_HEAD' | | From: | | https://github.com/JKrag/git-up | [deleted] | rjmunro wrote: | git config --global pull.rebase true | | You probably also want: | | git config --global rebase.autostash true | [deleted] | funkymike wrote: | I have this in my .gitconfig so the pull will fail rather | than merge. [pull] ff = | only | | If it does fail I can decide whether to merge or rebase. | lugged wrote: | Git init inits a git repo. | | Git submodule runs commands on submodules. | | What is hard about this UX? | | And it's not punishing you, its doing what you asked, to | pull into a non matching head, how does it know you're not | using git in the intended and distributed way? | | Btw, just quit the editor without saving, it aborts. | pjc50 wrote: | The "intended" way generates a completely spurious merge | commit - it doesn't represent a real commit, and rarely | do you care about keeping track of merges into a short | lived branch which are already tracked on master. | | Most people want a single source of truth workflow that | corresponds to the old total ordering imposed by svn or | p4. | klyrs wrote: | [misunderstanding removed] | smichel17 wrote: | In a thread about common sources of confusion, I think it | would be more helpful to leave the misunderstanding so | others might learn from it. Ie, edit to add "this is a | misunderstanding" to the top, not replace it entirely. | chakspak wrote: | You can also quit the CLI editor, e.g. vim. | chriswarbo wrote: | Git invokes an editor, for writing commit messages, etc. | (it looks in the VISUAL and EDITOR env vars). That could | be a GUI text editor, or something running in the CLI | (personally, I use emacsclient to open a new buffer in an | existing Emacs window) | | What they're saying is: if you quit that editor without | saving the commit message, git will abort. | handrous wrote: | I think they mean the commit message editor, which git | will use to open a temp file to save the message to if | you don't specify a message in-line with the "-m" flag | when committing, including when a merge commit is | initiated by a "pull". This happens on the CLI, it's just | usually (though doesn't have to be!) a command line | editor that it opens. I think vim's a common default. | | AFAIK whatever's opened does need to block the CLI, so | you can't use a command that opens a GUI editor then | returns immediately or git will interpret that as your | having closed the file without saving, but otherwise any | editor should work, CLI or GUI, and can be assigned in | your git config. | stormbrew wrote: | definitely agree, and I'm in the same boat. I don't even | think the data model of git is that hard to grok at all, it's | mostly that commands are very unclear on what they operate on | and in particular people get really tripped up about how many | levels of state there are (stage, working tree, local | branches, remote refs) that they have to interact with. | | Like, I've had to explain a lot of times why you `git pull | origin master` but when you want to interact with that remote | branch otherwise it's `origin/master` instead. The lack of | clarity is in what commands operate on what levels, with many | of them operating on several at once. | | There have been some efforts to reform the command set to be | more clear, like `git switch`, but the old commands will | persist forever along with a lot of other footguns (like `git | push --force` really ought to be replaced with `git push | --force-with-lease` and moved to `git push --force-I-really- | mean-it` so it hardly matters. | ethbr0 wrote: | > _levels of state_ | | This is the crux for me. Command naming is completely | unrelated to and unindicative of state. | | It feels like surely there's an opportunity for the basic | CRUD operations to be collapsed down into a standard | "{action} {source} {target}" style. | | There will be nuances, specifically around branching, but | the basics should be basic. As opposed to a Swiss Army | knife, where you have to pull out the scissors and squeeze | them three times before you can unfold and use the blade. | ryanmentor wrote: | Are there any git frontends that do this today? | unknown_error wrote: | The one built into IntelliJ IDEs is pretty good. | SourceTree is decent too. They are both cover the vast | majority of day to day operations. I only ever very | rarely have to resort to the command line for ritualistic | summoning of the git demons. | stickfigure wrote: | I've actually worked on git internals and I'm in the same | boat. | | As part of a security-related project some years ago, my | team and I hacked jgit to use SHA256, which required | changing the length of pretty much every on-disk data | structure. Sadly, there was (probably still is) no HASH_LEN | constant, just a lot of magic offsets strewn throughout the | code. I had to compare lengths against the git spec at | every step. | | And yet I still scramble for stackoverflow every time | something goes slightly amiss. | davvid wrote: | There's an ongoing effort to rework core Git so that the | hash implementation can be swapped out for eg. SHA256. | [1] | | jGit is actually a separate project from core Git, but | once it gets adopted into core Git we can expect that | jGit will follow suite, given that it's critical to | Gerrit and other projects. | | [1] https://lore.kernel.org/git/20191223011306.GF163225@c | amp.cru... | sam_lowry_ wrote: | What a pointless project! U hope you were paid well, at | least. | stickfigure wrote: | I was. But it wasn't _quite_ as pointless as it sounds - | the tool was a sort of tripwire-like system, with changes | shipped to an append-only log, that itself was | checkpointed in an early blockchain-ish structure. The | threat model was "nation state actor" so the client | wouldn't accept SHA1. | | It was actually a pretty cool system. I don't think it | was ever sold though. | unknown_error wrote: | Man, I thought zero days and secret backdoors were bad | enough. Now we have to worry about manufactured hash | collisions in all our repos' files dating back forever? | simonelnahas wrote: | That seems like an overkill. Couldn't you combine the | hash together with the date to obtain uniqueness? | unknown_error wrote: | The date isn't really meaningful since it can be set to | anything on a file. But if you can force two dissimilar | files to have the same hash, you can combine that with | some other attack to inject it into some sort of chain of | trust, whether it's git or some other type of checksum | based system. Then combine that with a SolarWinds like | attack and even if they try to revert to something from | years earlier, they can't guarantee that the rollback | files are still unaltered unless they had multiple hashes | to compare it to or diffed it manually. But multiply that | by X thousand files over Y commits during Z years and it | would be very difficult to detect. | fierro wrote: | can you explain the `git pull origin master` thing one more | time here? | stormbrew wrote: | like why it's different? | | `git fetch` (and by extension `git pull` when given a | remote) and `git push` copy data to and from a remote. | When you specify `git pull origin master` you're saying | "pull down a copy of the remote ref master from origin", | which it then saves locally as the ref `origin/master`. | | Everything under `origin/ _` (or really `refs | /heads/origin/_`) is just a cached pointer to the last | known state of that ref on the remote. | | All other commands operate only on these local | references. So when you want to refer to what you know to | be the state of things on `origin`, you can use | `origin/master`. Otherwise that command has no particular | knowledge of how to talk to origin. | | Incidentally this is a shortcut I use all the time to | update my local master from a remote: | | `git fetch origin master:master` | | Which is super unclear in its meaning but it means fetch | origin's master HEAD and put it in my local master ref. I | actually use this more often than git pull nowadays. | nicoburns wrote: | I tend to default to `git pull --rebase`. | pjc50 wrote: | I have this configured as default everywhere and strongly | believe that merge-pulls are always wrong. The first | place I used git we were learning together (i.e. nobody | knew what a sensible workflow was) and people would push | their local merge commits back to master. It was | horrible. | stormbrew wrote: | `git config merge.ff=only` is really helpful for | enforcing this. It makes you have to say what you want | for any non-trivial update of a ref through pull or | merge. | [deleted] | dorian-marchal wrote: | Also, one advantage of `git pull origin master:master` is | that you don't have to checkout master first. | mbeex wrote: | > (or really `refs/heads/origin/`) | | It is worth the time to fully understand refspecs. Once | people do, they tend to understand all essential | ramifications of branch and repository naming. | usr1106 wrote: | I don't think using `git pull` is a particular good way | of working. A pull is a fetch and merge or a rebase | combined. | | If it's difficult to keep your mental model of some | system up to date, I doubt that doing bigger steps at | once makes things easier. | | So | | 1. run `git fetch` | | 2. if the textual output does not tell you what has | happened, run `gitk -all` | | 3. Decide what to do. Rebase, merge, whatever. | | Of course if you know exactly what you are doing, pull | can be fine. If you changed the repo yourself on another | computer that is the case. Otherwise, how can you know | your second step, before having even seen the data you | are operating on? Well, it _can_ work, but if it doesn | 't, don't complain. | xorcist wrote: | This is literally the first advice I give when teaching | people git. The first months of use, just run the two | commands separate. Many mistakes are avoided that way. | u801e wrote: | > I don't think using `git pull` is a particular good way | of working. | | I agree. For a DVCS like git, separating the network | transaction from updating the working copy on disk is the | best way to go about it. Going in the other direction, | this is the default since git add, git commit and git | push are executed separately. | mikepurvis wrote: | What's wrong with `git push -f`? When I'm working on a | branch that's been previously pushed with `-u`, it's pretty | normal to force push it, particularly if you're amending or | reordering commits in response to review feedback, or | rebasing due to conflicts in preparation to merge. | stormbrew wrote: | changing `-f/--force` to act like `--force-with-lease` | would have no effect on that flow whatsoever. What it | would prevent is you accidentally overwriting something | on the remote because you didn't know its current state, | potentially silently backing out changes someone else (or | perhaps you yourself on another machine) had pushed. | | All it does is add this simple check before actually | pushing: if (remote_ref("blah") != | local_ref("remote/blah")) fail(); | | Most of the time it doesn't matter, and for most people's | uses of --force it would have no effect (because most | people are just pushing to a branch they're the only one | pushing to). But every now and then it helps a lot to | avoid losing data. | zoomablemind wrote: | I wonder should Undo as a concept apply to all Git | actions/commans which have state side-effects on the repo or | work dir OR should Undo only cover certain operations (which | ones)? | Filligree wrote: | Take a look at https://eagain.net/articles/git-for-computer- | scientists/? | | Maybe you've already read it, but this is what let _me_ grok | the underlying data. | romwell wrote: | I think the parent commenter says that they _do_ understand | the underlying data. | | It's just that the command-line interface is very opaque | regarding what it does to that data. | | For instance, say I want to apply the last three commits I | made in one branch to another branch. It's a very simple | operation conceptually. | | Good luck remembering that the command that does it is | _rebase_ , and what the arguments for it are. | cxr wrote: | The parent commenter makes it clear that they already grok | the underlying data. The problem with Git, as explained so, | so many times, is its horribly intuitive mapping from UI to | the operations those commands preform on that model. | | Comments like this, which points to a resource intended to | help people "grok the underlying data", has the effect of | seizing the focus of conversation and implicitly | retargeting it to be concerned with with people who _don | 't_ understand the underlying data model. When you been | through this enough times, it just comes off as incredibly | annoying and a source of tiresomeness. | pizza234 wrote: | Are you using Git via GUI(s)? | | Between my colleagues, there is a strong correlation between | using a GUI, and messing up the repository. | | I agree that Git's UX is pretty bad (checkout overloading; | overlapping between checkout and reset; push overloading... | yikes!), however, I believe that in contexts where using Git is | a constraint, stop using GUIs is the best strategy one can | apply to improve the understanding. | woah wrote: | Sorry, I'm trying to get work done, not memorize an obscure | set of incantations like some kind of D&D wizard. If the repo | gets messed up, I delete it and reclone. | cerved wrote: | It's a handful of commands, very well documented with tons | of SO questions that is one search away if you can figure | it out yourself. | | It's something I use all day, every day. I'd say it's | worthwhile to learn if your daily job involves working | under source control | tailspin2019 wrote: | Yes I agree. If you're going to use git (whether by | choice or force) it is 100% worth learning the small set | of commands required to undo a screwup without needing to | reclone. | | Recloning to me is a bit like tearing your house down and | rebuilding it just because you painted your living room | the wrong colour (in most cases!) | Shacklz wrote: | I really understand your sentiment, and I've been there for | long enough myself - but once you have a somewhat decent | understanding about gits internal data model, the commands | that allow you to clean up pretty much any mess (reset & | reflog probably being the most prominent ones) start to | somewhat make sense. If you had previous exposure to | anything computer-science, it very likely won't take more | than a few hours until the puzzle pieces start to come | together. | | And it's time well-spent in my opinion; git will probably | be one of the longer-lasting constants in software | development. | dec0dedab0de wrote: | I use the Pycharm/Jetbrains Git GUI. At this point I can't | imagine effectively handling merge conflicts any other way. | | EDIT: Also, I really like being able to look at a diff of | every file before I commit, and easily choosing which files | to include in a commit. Too often I see people on the CLI | accidentally committing changes they didn't mean to, because | there is no easy way to check everything at the last minute. | tailspin2019 wrote: | Yes Jetbrains have totally nailed this. I have tended to | prefer the command line for git but the exceptionally | designed GUI support in Rider is fast changing that - | especially for rebasing. | tcoff91 wrote: | even if you use the git CLI you can still set up a | mergetool so that when you are resolving merge conflicts | you can use something like BeyondCompare or P4Merge to | handle the merge conflicts. | mixmastamyk wrote: | Meld | Hamuko wrote: | And every Xcode installation on macOS comes with | FileMerge.app. | fiddlerwoaroof wrote: | There's a really easy way to check the diff before | committing on the command-line: git | commit -v | | Displays a diff at the bottom of the editor that pops up to | write a commit message. | Ashanmaril wrote: | The Jetbrains IDE git GUI is by far the best git GUI I've | used, I feel lost trying to use git without it. | | There's a user request that's been sitting around for a | while to pull it out into a dedicated application, which I | could personally get behind since we have one project at | work that's pretty difficult to run outside of Eclipse | | https://youtrack.jetbrains.com/issue/IDEA-152437 | stevenhuang wrote: | What's wrong with 'git diff'? | | Then there's 'git add -i' to easily choose which files to | add | gitgitgit wrote: | I use Git via the GitHub Desktop client | (https://desktop.github.com) and find it _very easy_ to use | Git without issue by following a simple rule: don't be | clever. I have branches, I commit, I squash merge via a Pull | Request. No rebasing, no moving commits around. There might | be workflows where rebasing etc. are important and certainly | in those cases, using a GUI is probably not a great idea -- | but it's certainly possible to use a GUI without issue if you | keep your workflow simple. | phkahler wrote: | I squash locally, but learning to do that required learning | vim. Fortunately vimtutor. Then my distro changed the | default text editor launched from git... fortunately I knew | enough to get by with that one - which might be emacs but I | haven't verified. | | Git is really weird but useful. | gbear0 wrote: | The default editor is usually configurable (of course | you'd have to learn all the different contexts you can do | this from first to know this is a thing ... | discoverability is hard). | | For example in ubuntu you can do sudo | update-alternatives --config editor | | Some programs will use the environment variable $EDITOR, | so you can add this to your shell startup configs | export EDITOR=vi | | Or specifically for git cli you can run | git config --global core.editor vi | sethd wrote: | Git will use whatever editor you have defined in $EDITOR. | You can also define this specifically for Git via global | config (~/.gitconfig) if you don't want it to use your | session's $EDITOR variable: [core] | editor = vim | overgard wrote: | I find GUI's to be very helpful; most of my commits happen | through VSCode's commit panel. For my home Unity3D project I | use sourcetree because my commits unfortunately end up being | to a lot of unrelated files (blame unity), and having a UI to | stage them saves a lot of typing. I avoid anything like | rebasing (never got the point of that), but I use branches | liberally. I find with this setup, I only need to use a | handful of command line options, and I haven't screwed up a | local repository in a long time. | muststopmyths wrote: | If you are on Windows, Visual Studio's GUI is actually | quite good for staging, merging and diffing. I tend to use | it for most of those simpler kinds of things while still | doing commits, rebase etc. from the command line. | | Same for VSCode on non-Windows. | | I only mention this because I came to hate Sourcetree in | its newer iterations on Windows so much that I tried out | Visual Studio's support and was pleasantly surprised. | zubspace wrote: | I'm a huge fan of git fork [1] on windows (or mac). Looks | good, never failed me and does everything I need (branching, | rebasing, merging, squashing, cherry picking, blaming and it | can even show lost commits with reflog). And it performs | really well (in contrary to sourcetree). | | [1] https://git-fork.com/ | smilekzs wrote: | I disagree. | | First of all, a well-designed Git GUI (examples below) | exposes the git's underlying data model to you; in contrast, | the CLI obscures it until something breaks and you're forced | into it without context. Git operates on a graph and there is | simply no way around it. The more you're exposed to the | graph, the better you can mentally model it and ask it to do | the right things. | | While there are many half-baked Electron-based UIs that only | unnecessarily complicates things, there are good ones too: | | On Windows (and Linux thru Mono), I use GitExtensions. The | visualizations are sane and discover-friendly. It will tell | you what to expect. | | When I work on C++ projects, the one built into CLion | (JetBrains family; as mentioned by a sibling comment) is very | good on its own. What impresses me the most is that has good | visual support of a patch-oriented workflow. You can work | with multiple "changelists" offline, shuffle individual | changes around, seamlessly convert between changelists and | patch files, and (most importantly) still work nice with the | vanilla git model as the "actual history". It also works | transparently with conceptually monorepo projects that have | multiple physical repos, allowing you to do simultaneous | commits. | | I feel VSCode, GitHub client, Kraken, and several other | Electron-based stuff, are too focused on the "polish" than | substance, or are too opinionated to be used across repos I | don't own. | jonnycomputer wrote: | So back when I was learning git, I was very shy about using | any GUI because I was afraid that it would make learning | how git works that much harder. I think that I somehow felt | that the CLI was more fundamental, in some way. But I think | you are right, and I was wrong. A better interface that | puts the graph front and center would have led me to learn | it so much faster, especially when it also exposes the | command line equivalents, as magit does (or so I've heard). | [deleted] | cerved wrote: | The CLI doesn't obscure as much as presupposes that you | understand internal workings of git. | | All GUIs are not created equal. The JetBRains GUIs are | pretty good. Others try and impose git "their way" and just | invite creating a mess. | swader999 wrote: | I agree and limit Git Gui usage to read-only use, any mods to | git I use command line. | yxhuvud wrote: | Git Gui is a decent tool to compose commits, but for | everything else I can't see myself using anything but the | command line. | rjmunro wrote: | gitk (and similar) are great for browsing the history and | figuring out what is going on. I couldn't live without | it. | tcoff91 wrote: | I do virtually everything with Magit. It's the best of | both worlds IMO. You still need to actually understand | git and its commands but it's like using the CLI with far | fewer keystrokes and a better log interface than the CLI. | PufPufPuf wrote: | Funnily, I use a GUI almost exclusively to resolve mess-ups: | Ungit is a great tool to understand the current state of the | repository and fix it. | an_opabinia wrote: | Not a single person I've met using git in the last decade has | thrived using a UI for it. | lanstin wrote: | magit (for emacs) is quite good. But I still only use it | for browsing around mostly, or single-file commits. For | serious work, I start with git status, and then git diff | all the changes, and then group them and then commit then | in groups, then pull --rebase then push | HEAD:good_branch_name (by the time I've done all the above, | I have a better chance at a good name than I do for the | first commit). Then over to PR land, where we have "ff if | possible and delete source branch." | animal_spirits wrote: | I've said this in other threads but I'll proselytize here | as well. I really started to grok git after using the | lazygit terminal UI. I think it's really handy to see what | the current "state" of git is in and how to browse it | easily. Would continue to recommend. | | https://github.com/jesseduffield/lazygit | oblio wrote: | That's a failing of Git. TortoiseSVN brought source control | to millions of people. A good tool should be fully | embeddable in a UI, 15 years after its launch. | OJFord wrote: | Or a success of git? No good GUI exists because they | realise they'd just be recreating things that exist, but | with a GUI frame? | | If you wrote git 2.whatever from scratch would you | structure rhe commands a bit differently? Yeah, sure, | probably; but I always think these threads are way | overblown. The common stuff that you use frequently.. | well you use it frequently, so either you remember it as | a result or you use the alias feature so that you can. | For the less common stuff.. if you have to look it up in | the excellent documentation, is that a failing? | [deleted] | approxim8ion wrote: | We still use tortoiseSVN at work. It's crude but | shockingly simple to use. Moving to git would be a | significant expense just to train people not to break | things and to get them used to CLI. | somethingor wrote: | TortoiseGit exists too and is fantastic IMO: | https://tortoisegit.org/ | dragonwriter wrote: | > Not a single person I've met using git in the last decade | has thrived using a UI for it. | | I do most of my git through one or another UI (right now, | mainly the integrated functionality in VSCode, a gitflow | workflow extension for VSCode, and repository history graph | extension for VSCode that supports doing operations against | branches/tags/commits from the graph.) I feel loke I'm | thriving that way. | | Its not a substitute for knowing git, though, and I think | that people who lean on a UI as a substitute for knowing | what is going on underneath rather than as a convenience | layer are not likely to thrive. | [deleted] | MayeulC wrote: | > What does "git reflog" or "git reset --hard ...." do? What | are the implications? | | This is supposed to be covered in `man git reflog` and `man git | reset --hard`. I admit that it could be more readable though. | Currently, it's more of a technically-correct introduction than | a layman's. I guess it's really more of a documentation for | experts. Some have made fun of this: https://git-man-page- | generator.lokaltog.net/ | | In layman's terms, `git reflog` is the history of the positions | you were at: you'll see every commit you've visited recently, | so as long as something was committed, you won't lose it. It's | here in case you lose some commit identifier (for instance you | finished rebasing but are not happy with the result: the branch | now points to the sad commit. Grab the reflog, copy the commit | identifier and reset the branch to point it to where it was | before). | | And `git reset --hard`... `git reset` changes the branch "tip" | (pointer) to another commit: the commit tree always exists. | Branches are "named commits". `git reset` moves these tags | around. The `--hard` part "just" replaces the entire content of | your working directory (including non-committed changes) to the | commit you give as a parameter. With no parameters, it just | resets to the latest commit in that branch, so it's like saying | "clean my working directory back to what was committed, discard | my changes". Perfect for losing work. | | I agree that git "porcelain" commands are sometimes ill-named | and a bit counter-intuitive to grasp. For me, learning git paid | of (sort of: I don't spend time fighting my issues, I spend it | helping others fix theirs). | | I'm keeping an eye on better-designed alternatives like pijul. | mercurial is interesting and has better-named command, but I | sunk some time learning git already, and know it better, so hg | has very little more to offer to me. | Hamuko wrote: | > _The truth is, while we use git every day, most people really | don 't understand how it works._ | | Most people don't know how the Internet works and yet it's | widely used. | | You don't need to understand the inner workings of git. You | just need to know some commands and some basic concepts. | agucova wrote: | The problem is not knowing git internal can very easily | backfire by deleting data, rewriting history, etc | matheusmoreira wrote: | > Most people don't know how the Internet works and yet it's | widely used. | | Yeah. I've met many developers who have no idea what a cookie | even is, people who have never read a single IETF RFC. | uvesten wrote: | Me too, far too often. Those developers are most often | negative contributors... | ycken wrote: | > The truth is, while we use git every day, most people really | don't understand how it works. | | It is a tool. One should not need to understand the inner | workings of a tool to use it. How many APIs do we use where | knowing how it does what it does is required? Whether it's | Stripe or Node or Bundler or ..., the user does not have to | know what happens inside. The need for incantations makes some | people feel powerful or exclusive. I just want my tools to do | their job so I can focus on doing mine. | lugged wrote: | I come across this attitude a lot. | | Usually my response is if you use something daily, and you know | you lack the skills to use it effectively, why don't you | improve your knowledge and seek out training or education? | | Do you treat a new programming language or framework with the | same disdain? | | I know I'm gonna get some hate for pointing this out but this | same disdain is what causes things like the branchless | workflow. A workflow that hamstrings yourself to git stash as a | poor man's branch. I get it, I used that as crutch for years, | then I spent some time learning git properly. | | Most people haven't even watched the one hour talk where Linus | talks about the design and building of git. | | One hour might sound like a lot to understand why branching is | so amazing, and why distributed source control is hard but it's | a tool I've used for almost a decade and won't stop using for | the next decade. I think it was worth it. | Ensorceled wrote: | At one time I was an expert in 'C'. I was the goto guy at our | company for porting and performance issues and was often just | handed the entire project if it involved porting. | | I have no memory of any of that beyond the basics now. Git is | like that. There is no way I will remember commands I only | use once a quarter or so when something goes wrong. | lugged wrote: | I don't know what to tell you, commit more code? Branch | more? Work in teams? | | Maybe git isn't the right tool for you? | | I have a set of commands I use multiple times a day, for | everything else there are manuals and docs to reference. | | Git branch, commit, rebase, merge, clone, check out, pull, | push, submodule, remote, and maybe a couple more, are there | specific commands you don't use daily? Other than remote | and submodule I use all of those almost daily. | megameter wrote: | That's nice, but most of us here are version control | consumers, not version control professionals. We need | something that has very few knobs to turn because our job | is focused around delivering value through other tasks. | | Git is highly professionalized. It has layers of modal | state. That is built into the operating model. It is made | for Linus Torvalds, a professional merger of code. If you | are using all of those commands "almost daily", you are a | professional code-merger too. | Ensorceled wrote: | I was replying to this part of your comment: | | > Usually my response is if you use something daily, and | you know you lack the skills to use it effectively, why | don't you improve your knowledge and seek out training or | education? | | Seeking out that training would be useless since I don't | use git enough. | | > Maybe git isn't the right tool for you? | | Git is definitely the tool for me. It's better than any | other available tool for my situation. | | Why the hell would I branch more? Just to get better at | git? Sorry, I'm sorry that I work on a small team! Maybe | I should go back to CVS? | | Stop gate keeping. | eric4smith wrote: | Bingo. | arxanas wrote: | > I know I'm gonna get some hate for pointing this out but | this same disdain is what causes things like the branchless | workflow. A workflow that hamstrings yourself to git stash as | a poor man's branch. | | FYI, the branchless workflow linked to in the post is really | the opposite of this. It encourages making commits even more | often than you would in the traditional branching workflow, | and discourages using the staging area or stashes when | commits would work fine. | MehdiHK wrote: | Git Tower GUI app has undo feature too, which is very handy. They | announced it in this post: https://www.git-tower.com/blog/how-we- | built-undo/ | voiper1 wrote: | Reference to a helpful wizard for fixing your git mistake: | http://sethrobertson.github.io/GitFixUm/fixup.html | Egoist wrote: | Wow, probably one of the best guides i have seen for git. Wish | i knew this existed when i was a beginner | thewebcount wrote: | I'm sorry, but how many bits of git's UI do we have to force | users to manually replace before we realize that the entire | problem is git's UI? | | Between the tone deaf responses here about "using a GUI client is | the problem," to the tone deaf responses of "you just have to | learn it's internal architecture," it should be obvious what the | problem is. The problem is not just being able to undo a mistake | (though that's certainly _one_ of the problems). Git is an | incredibly user-hostile experience, and someone needs to fix or | replace it. Can we just say it out loud and stop pretending that | the problem is the literally thousands of users who have problems | using it? | TobTobXX wrote: | Admittedly I did spend like a combined hour troubleshooting git | over the last two months. | | But git saved me an immeasurable amount of hours in return. I | was asked what I worked on some specific week back in may -- | git saved me. I had to look up what performance my program had | before a specific change -- git saved me. I had to try stuff | out without messing up my codebase -- git saved me. | | True, I invested quite a few hours and I still do, but I think | the investment pays itself off. I'll never ever do a project | without git. | gumby wrote: | > tone deaf responses of "you just have to learn it's internal | architecture," | | Why is this tone deaf? It's a development tool for | _programmers_ and the internal structure is conceptionally | pretty straightforward. Understanding your tools is pretty much | prerequisite. You don't have to have written a compiler to use | one, but you do have to have a model of what it does. Git is no | different. | rjmunro wrote: | There is no doubt that a bunch of the general commands are | really poorly named, or mixed together. `git checkout branch` | means switch to a branch - that's fine. But `git checkout | filename` means "undo changes to the file". What? That's | totally insane. | | `git branch new-branch-name` means create a new branch. Great, | but it doesn't check out the branch, which you want like 99.9% | of the time. If you want to do that, you use `git checkout -b | new-branch-name`. Yes, a third separate use for git checkout. | | Why not (e.g.) `git branch -c new-branch-name` with a config | option to make `-c` the default if you want it? | | If you rebase and push, it tells you to do a `git pull` to | "fix" it, when in every workflow I've ever done, you want to | add a `-f` and push away, just be aware that you are | intentionally overwriting the remote branch. | ufo wrote: | By the way, I recommend using `push --force-with-lease | `instead of `push --force`. This way it doesn't destroy the | remote changes if someone else pushed while you weren't | looking. | RvdV wrote: | New commands 'git switch' (git switch -c for new branch) and | ' git restore' address exactly that issue and are available | on newer git versions, so it's being worked on! | | I do agree with the second example. Pulling and merging with | remote after a rebase makes a terrible mess! | npteljes wrote: | And if I create a new branch locally, why must I specify what | name I'd use for it on the remote? Why would I like an | _other_ name I wonder? It 's fantastic that it can do this, | but the default should be the branch name I'm using and | that's that. | mdaniel wrote: | > But `git checkout filename` means "undo changes to the | file". What? That's totally insane. | | Heh, and I'll do you one better: it's _unstaged_ changes, so | it won 't put the file back to the HEAD version 100% of the | time >:-) | cerved wrote: | Git checkout branch means change the entire working tree to | the reflect the state of the branch and git checkout file, | checkout the state of that file in HEAD. Both commands to the | same thing, change the state of your working tree to reflect | a point checked into version control. | | It sounds like you are unaware of git switch | branch | | and git switch -c new-branch | Vinnl wrote: | Just a tip: when teaching people, the readable alias is | easier to remember and understand, i.e. | git switch --create new-branch | riquito wrote: | It was a good example: it was obvious by the name of the | branch and he/she was teaching the real word use case | lawn wrote: | This is the one thing I took with me from The Design of | Everyday Things: usability design matters, and it matters a | lot. | sloucher wrote: | Last time I checked, 5 of the top 10 questions on StackOverflow | were about Git... | adamrezich wrote: | still true! but that isn't a great metric necessarily, as #10 | is "What is the "-->" operator in C/C++?" | https://stackoverflow.com/questions/1642028/what-is-the- | oper... which is just a novelty rather than a common question | greenshackle2 wrote: | Maybe because like 90% of devs use git; there's no language | or framework that is used by so many. | [deleted] | nexuist wrote: | The problem is just that collaborative text editing between | multiple users simultaneously is hard. It's a human problem and | git attempts to be a technical solution but the abstraction | fails at the edge cases. | | Regardless, what's so bad about deleting the repo and pulling | from remote if you can't figure out why you hosed it? It's not | like it costs you anything to do `rm ... && git clone ...`. And | it's not like this happens daily either. | | In the rare case that someone hoses remote, yes you'll have to | do some weird git-fu to get everyone working again, but it's | really hard to hose remote if you stick to the pull -> commit | -> push -> merge pattern, which is what 99% of users are doing | anyways. I've used git for 9 years and I've never had to spend | longer than an hour troubleshooting git based BS. And if you'll | remember, 9 years ago git wasn't the clear winner, it had | competition via SVN and Mercurial. Both of them are practically | irrelevant at this point so however bad git's UI was, it's | clearly better than anything else that existed before. | vxNsr wrote: | GitHub is what made git so popular, git wasn't inevitable, | and GitHub didn't become huge because of git, GitHub's big | innovation was attaching a social network to a software/code | repo. It's what made it way more popular than basically all | the competition, which were just software/code repos but | didn't have a great network/social story. (Also at the time | GitHub was coming out, the biggest player in the space | decided to monetize in an annoying way.) | chriswarbo wrote: | > It's a human problem | | If it were a human problem, how could alternatives like | Mercurial and Darcs get consistent amounts of praise for | their intuitive workflows? | | > 9 years ago git wasn't the clear winner, it had competition | via SVN and Mercurial. Both of them are practically | irrelevant at this point so however bad git's UI was, it's | clearly better than anything else that existed before. | | SVN isn't distributed; it mostly tried to replace CVS, which | it managed to do very successfully. | | As for DVCS, the fact that system X became more popular than | system Y doesn't mean that _every_ aspect of X is better than | Y. Many would say git succeeded _despite_ its awful | interface. As far as I can tell, the main feature of git was | its speed; that made it usable for huge projects like Linux | and Xorg, and this endorsement from high-profile projects | gave git the edge for DVCS hosting sites like Gitorious. Then | GitHub came along, and grew into such a behemoth that git | became the de facto standard. | | See also: WorseIsBetter | umvi wrote: | > If it were a human problem, how could alternatives like | Mercurial and Darcs get consistent amounts of praise for | their intuitive workflows? | | Because maybe mercurial's real problems wouldn't show up | until people started using it at scale. | | This is a classic problem that happens time and again. | | Windows vs. Mac back in 2005: | | "Windows having malware is a human problem" | | "If it were a human problem, how could alternatives like | Mac get consistent amounts of praise for their lack of | malware?" | | Turns out it's just because Mac didn't have a big enough | market share. As soon as it did, Apple could no longer | claim that Macs can't get malware because they can and do. | | Similarly, if you scaled up the number of Mercurial users | by several orders of magnitude so that it was now | "mainstream", I'm sure some of its lesser known pain points | and/or counter intuitive behaviors would start floating up | to the top 10 HN stories. But since hardly anyone uses | Mercurial vs. Git, that doesn't happen. Just because a | minority of users praise something (<insert lesser known | language>, <insert lesser known DB>, <insert lesser known | VCS>, etc.) doesn't mean if you scaled up the userbase one | or more magnitudes it would continue getting that level of | praise from all users. | Izkata wrote: | > Because maybe mercurial's real problems wouldn't show | up until people started using it at scale. | | I actually tried both git and mercurial almost a decade | ago having had only experience with subversion, and found | git to be much easier to understand and use. I don't | recall what those pain points were, and am sure I | couldn't describe them correctly if I did remember, but | because of that I do expect such things to start popping | up if more people used it. | daxelrod wrote: | I agree that collaborative text editing between multiple | users simultaneously is hard. | | That doesn't mean that Git couldn't have a much better UI for | this problem than it does. And while I agree that Git seems | to have mostly won over SVN and Hg, it doesn't follow that | it's because of its UI. (For example, I think that a lot of | Git's success actually comes from the UI of GitHub, not Git | itself, but I don't have evidence to back it up.) | | Take a look at the Research section at the bottom of | https://gitless.com/ for work that's been done on how to | accomplish the same operations with a simpler conceptual | model. | lanstin wrote: | This is the real interesting problem. Even simple subtle | decisions like "should this list be kept sorted, or have | new things added to the end" determine under what | conditions you will hit a new conflict and when you won't. | List of enums, add to the end, and if 2 branches grab the | next enum value then you'll see a conflict. List of lets | say URL prefixes keep in order, then most randomly added | URL prefixes will not collide or conflict, only conflicting | if you get 2 things trying to operate on the same prefix. | FractalHQ wrote: | Wow. Reading the home page of gitless made me both excited | to use it and angry at how poorly designed git's UI and UX | are. Thanks for sharing this! | quickthrower2 wrote: | I feel that I only understand git because I'm forced to use it | for years, but the experience could have been a lot less | painful. I use a GUI for sure. Do people really diff and | resolve big conflicts at a command line? I never figured out | how. | cerved wrote: | git mergetool | | or git checkout --ours/theirs && git add . | rjmunro wrote: | Just delete the bits you don't want and `git add` | | It helps a lot to set: | | git config --global merge.conflictstyle diff3 | | then you can see the before as well as the 2 changes you are | trying to resolve. | renewiltord wrote: | It is interesting. I've never had any trouble with git. I think | the reason is that I learned it relatively early in my career and | so I had the luxury of "What's the right way to resolve this | situation?". I have never lost data despite using filter-branch, | rebase, bad merges, bad rebases, bad branch deletes... | | Still, the UX sugar of undo sounds quite nice. I only worry about | introducing something heavyweight into the thing. If I use | branchless will it force others to use branchless too? | arxanas wrote: | No, it doesn't force others to use branchless at all. The git | undo data is stored in a separate database in your .git | directory, so other people won't have access to it. (Of course, | this means that they can't use git undo on your actions.) | amelius wrote: | Would this work on a pull from a remote? | | Or how about after pushing to a remote? | arxanas wrote: | Pull from a remote: yes, it will rewind the local references to | their old positions. | | Push: sadly, no. | phonebucket wrote: | git config --global alias.undo 'reset --soft HEAD~1' | | Not that I would include this in my own shell. To the authors two | example uses: 1) Undoing an amended commit. But if you're | comfortable amending a commit, can't you just amend your amended | commit? 2) Accidentally commiting an incorrectly resolved merge | conflict. Revert the change if you want to be non-destructive. | Reset HEAD~1 otherwise. | renewiltord wrote: | 1. I believe it's not that you want to amend it, but that you | want to restore its pre-amended state. I would use the reflog | to look that up and then reset to it but this makes that easy | and hence, more accessible (which is good) | | 2. Yeah, but I think the UX improvement of a single command to | say "Go back to where I was" is reasonable. | optymizer wrote: | This is an excellent idea and I'm glad it's making its way into | the open source community. | | My company has an equivalent to 'git undo' that basically undoes | anything you just did to your local repo. | | It's just so freeing. Sometimes you need that Ctrl+Z so you can | undo and redo things correctly. It gets your mind back to | whatever you were doing before without needing to debug wtf just | happened. | zach_garwood wrote: | This seems like putting a training wheel on a training wheel. git | is already the easiest to understand of any VCS that I've used, | and it's somewhat hard to do something in git that can't be | reversed. As the articles states, it's unlikely you'll ever lose | your changes. Further, this doesn't seem to be that different of | a concept from git reset, so why not learn reset instead of yet | another command? | sedatk wrote: | > git is already the easiest to understand | | You mean Mercurial :) | zach_garwood wrote: | I concede the point :) | jcranmer wrote: | > git is already the easiest to understand of any VCS that I've | used | | _Breaks down in uproarious laughter._ | | One of the worst offenses git is its use of multiple different | jargon terms for the same concept; indeed, it's the only VCS | I've used where reading help leaves me _less_ sure than when I | started if it does what I want it to do. | | If I accidentally leave my system in a weird state (say, I'm in | the middle of a git rebase and I forgot to git rebase | --continue), and I start doing some regular git commits, the | resulting mistakes are, while possible to recover from, | difficult to do so unless you know git's internals. I have to | use the "what's that git command to list the commits I just | dropped on the floor by accident?" with surprising frequency. | zach_garwood wrote: | What are the jargon words youre referring to? In my | experience, it uses the same jargon as the other VCSs. | | Perhaps you have a different workflow than me, but I don't | find myself rebasing all that often to begin with. I | generally don't rewrite history unless I truly fucked up. And | since I'm in "I fucked up" mode, I take extra care with | commands I type. | | I don't wanna be like Apple and say "You're holding the phone | wrong," but maybe you shouldn't be doing frivolous rebasing. | jcranmer wrote: | The staging area (aka "index" aka good god don't try to | read git glossary's index for this) is a bad one. There's | definitely several cases where I've read the documentation | and struggle to figure out if it will or will not affect | the working checkout or not. | simias wrote: | Hard disagree, git's docs and UI have improved over the years | but every time I have to teach it to a beginner I realize how | arcane and scary it is, especially when compared to old school | centralized VCSs like subversion. | | Not that I'd trade git for subversion mind you, in the hands of | a trained individual git is a godsend, but the training part | can be arduous. | | Even among DVCSs I'd argue that mercurial for instance is | vastly easier to pick up. | zach_garwood wrote: | If it's an issue of having to read the docs or the man, well | I've been at work like this for a little over a decade and I | still have to pull up a reference when I want to do something | nontrivial in, not only git, but pretty much every cli tool I | use on a regular basis. Cli tools, frameworks, libraries, | languages... I have to pull up a reference for everything I | do as a programmer, so it's hard for me to muster up the | indignity for having to look up how git works. | | If it's a matter of understanding the flow of the tool, then | I will have to concede that mercurial probably is easier to | understand for the beginner. | rileymat2 wrote: | `git add <file>` | | Wait, how do I remove it from staging? It seems there | should be some symmetric operation, `git remove <file>` or | something. Maybe git rm `<file>`, whoa don't do that. | | No, it is `git reset HEAD -- <file>`. There is no mental | symmetry. | | Or why use add at all? What am I adding it to? It is so | generic, why not `git stage file` and `git unstage file`? | | I agree that you need to read and learn tools, but there is | a lack of consistency and symmetry in many of the commands | which make it harder. | arxanas wrote: | Git reset doesn't e.g. reset the positions of multiple branches | to their historical positions. In fact, some of that data can | be lost forever to Git (branch deletions are not tracked | anywhere). | quickthrower2 wrote: | Nice, I can evolve from https://xkcd.com/1597/ | float4 wrote: | > novice users are terrified of it. When they make a mistake, | many would rather delete and re-clone the repository than try to | fix it | | In my experience most beginners use a GUI like Atlassian | Sourcetree or the Github desktop client. It's a lot harder to | make mistakes using the GUI in my experience. | | I still really like this idea though; eventually a subset of the | beginners wants to learn the git cli and that sure seems scary at | first. | Osiris wrote: | For JetBrains users, there is a built-in Git GUI as well. | | It's not as easy to use as SourceTree, but since there's no | SourceTree for Linux, it works well enough. | jahnu wrote: | Can I give a shout out to Fork here for being another great GUI | for git. I'm not affiliated with them in any way. Just a happy | customer. | | https://git-fork.com/ | dewey wrote: | Agreed, another happy Fork user here. I switched from Tower | as it just got more and more expensive and added features I | don't need. | contriban wrote: | I occasionally screwed it up even with a GUI, possibly because | I was trying to recover something and then got lost. Once I had | to abandon the master branch for a year because I didn't know | how to fix it. | | A year later I had probably learned how to force push correctly | and took hold of it again. | | However I do think the GUI is great for git and that's why I | use GitHub Desktop. It's super simple. Most other GUIs try to | wrap git concepts too closely for comfort. | lukeinator42 wrote: | I really love the Jetbrains GUI built into their IDEs for this. | arxanas wrote: | GUI tools are a great step forward in my opinion, not because | the GUIs are necessary, but because the Git command-line | interface is really terrible. | | I would like to see a GUI adopt these concepts. There's no | reason why we should limit the commit graph display to only the | current time, when we have enough information to scroll through | its past states as well. | Vaslo wrote: | I used GIT recently for tracking an SSIS package and despite many | commits I still have no idea whether I should use a rebase or a | reset or a hard reset. Reading the manual does not help. I just | simply want to undo a mistake. Glad I am not the only one who | feels dumb about this. | noxer wrote: | obligatory mention of fossil-scm.org just in case someone don't | know yet and would like a version control system++ that actually | works for/with you. | gerbilly wrote: | What makes git really complicated is that for every command you | type, there are two things that may be affected: | | * the working copy | | * the graph | | And it gets better, if any file gets disconnected from the graph, | it can be hard to locate. (Yes I know, it can be found in the | reflog) | rags2riches wrote: | Let's not forget about the index. Or is it called the staging | area? | RichardCA wrote: | This conceptual overloading of language can be traced back to | Linus' first commit. | | https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23. | .. | | The original idea was "current directory cache" and that | still pops up in the syntax. | | I always run "git diff --cached" as a last sanity check | before a commit. | OhNoMyqueen wrote: | The most painful mistakes beginers endure with git are | irrevocable code removal from the current working directory | because of bad usage of `git clean`, `git reset` (or `git merge` | if you're brutish enough). This problem cannot be solved by using | git, because git doesn't have any reference to such code. | juped wrote: | Also from deleting their whole checkout. | Leherenn wrote: | A bit less painful, in the sense that you probably won't lose | work, but still quite a headscratcher is line endings issues. | Not amount of `git checkout .` or `git reset --hard` will help, | and you just have massive diffs with no obvious change. I | recloned the repo quite a few times in my younger days over | this, and I still have to think deeply to be sure to use the | correct configuration. | nsomaru wrote: | Am I doing things wrong if I have never used these commands? | rjmunro wrote: | No, IMHO you are doing things right. I virtually never use | those commands, I've been using git for well over 10 years, | and have totally got used to all it's quirks. | jonahx wrote: | Probably not using git ideally. Do you clean your history | after working on a feature? | jdauriemma wrote: | Try not to think of it in terms of right and wrong. `git | clean` is useful, though not "can't-live-without-it" useful. | I couldn't imagine my workflow without `git reset`, though, | and I recommend checking it out! | anamexis wrote: | I agree, these are the only times I've irreversibly gotten | myself into trouble. | | I think it would be possible to solve these with git, by doing | something like automatically running a `git stash --include- | untracked` before an operation that can clobber untracked | files. | kahkeng wrote: | I find it pretty useful to use the `--patch` or `-p` option | (also a mnemonic for "prompt") to various commands: | | `git add -p`: prompt which hunks should be added to staging | | `git checkout -p`: prompt which unstaged hunks should be thrown | away | | `git checkout HEAD^ -p`: prompt which hunks from HEAD should be | discarded | | `git reset -p`: prompt which currently-staged hunks should be | unstaged | | `git reset HEAD^ -p`: prompt which hunks from the HEAD commit | should be unstaged | | Nice thing is that you get interactive yes/no prompts with a | preview of the change for each hunk, and you can also quit | early if you realize it's not the command you want. | | Doesn't fully address the potential for lost changes, but slows | it down by adding an interactive roadblock for each change. | secondcoming wrote: | hunk? | abdusco wrote: | If you're using JetBrains products, you can view the history of | the changes for the whole project and revert mistakes by right- | clicking the project > Show Local Changes. | | https://twitter.com/abdusdev/status/1403050600925962247 | rags2riches wrote: | Don't forget `git checkout`! | | When I help people get started with git, I tell them several | times to commit as often as they can. If they committed it, I | can probably save them when they think they lost something. | alkonaut wrote: | I hate git passionately, but I still find it somewhat | understandable. I understand what it does but that of course | doesn't change my view that its UX has the elegance and | consistency of an early php draft that went through a document | shredder. | | Git has a nice elegant layer underneath though. The DAG of | commits is a very nice model, covered in a layer of terrible | commands, and a few rather unnatural abstractions like the | staging area. | | I think to effectively use it you need to work with your brain | squarely in that lower layer. Trying to think in terms of | sequences of commands rather than a tree of commits and | references is hopeless. | | The fact that the UX concepts (commands, working copy, reflog | staging area, ...) and the underlying model (graph) are difficult | to reconcile is git's biggest weakness. | | The difficulty with which is models some of the most common use | cases (centralized, often including a few large binary files) is | another. | yarg wrote: | There's a limitation to the DAG model that has bothered me for | a long time. | | I don't always want a branch to descend from a commit - | sometimes I want it to descend from another (less featureful) | branch. | | I want the ability to say that branch 1.1 is equivalent to | branch 1.0 + {some set of changes} is something that would be | exceptionally useful in a lot of circumstances. | | (And I know this would create some new fun and games from a | conflicts perspective, but I think it'd be worth it for any use | case that involves long term maintenance of different releases | of the same piece of software.) | leafmeal wrote: | So like a branch that automatically rebases on another | branch? I think the issue with this is the inevitable | conflicts and race-conditions. While nice in theory, often | you need manual control to sort things out. | yarg wrote: | Not quite - branches get ancestors. | | A new repository starts with an empty branch. | | A DAG gets layered on top. | | I mentioned conflicts, but can you explain where race | conditions would arise? | chuckdries wrote: | gitkraken also has an undo button | Simplicitas wrote: | This is an awesome idea. Can't wait to hear the objections from | the purists. | RichardCA wrote: | The purist will say: You are always free to write your own | porcelain. | idoubtit wrote: | I've watched the first case: amend a commit then undo. And I | believe it shows serious shortcomings : | | - The interactive interface of `git undo` is probably too hard | for beginners. Designing simple interfaces is hard, and you | can't pplease everyone. | | - It seems `git undo` simply does a `git reset--hard` toward a | designed commit. The user probably expected to return to the | state _before the last git action_. Instead `git undo` reverted | the amend, but also reset the index and remove the local | changes. At this point, the beginner could scream "Undo lost | my changes! I just wanted a second commit instead of an amend." | | Undoing could mean `git reset --hard {hash}`, but in many cases | `--hard` would have unwanted effect and the default `--mixed` | would be more suitable. But even in this case, it's not a full | undo, since the index is not preserved: you don't end up in the | same state as before the `commit --amend`. | spicybright wrote: | Why is it so hard to implement a git undo? You have a | previous state, and a current state. Just roll it back. | arxanas wrote: | There is a design to address undoing changes to the index: | https://github.com/arxanas/git-branchless/issues/10 | | It runs a `git checkout`, not a `git reset --hard`, so it | will stop you if there are incompatible changes. Of course, | if `git undo` can be made to lose your staged or unstaged | work, then that's a bug. | | Fortunately, you can undo the result of any `git undo` with | another `git undo` that goes one more step back in time. | 29athrowaway wrote: | There is a large graveyard of "simple git tools", many of them | portray themselves as happy GUIs that prevent you from learning | git... | | None of them works. At some point you will be told to fix the | problem by hand. | [deleted] | robin_m wrote: | Quick tips for people that find git confusing: | | - Use a recent version of git. The error messages have improved a | lot, have been localized (unless you do `LANG=C git ...` to be | able to search it on internet), the UI has improved, `git status` | is more helpfull, ... | | - Create an alias for `git log --graph --decorate --oneline | --all` or something fancier with `--format`. `--graph` should | help you a lot to visualise stuff. - Don't use `git reflog` but | `git log --graph --reflog`, it's much easier to visualize. | | - Never use `git checkout`, but `git switch` and "git restore` | that were introduced in git 2.15 IIRC. They are much less | confusing and error prone. | | - `--patches` (`-p` for short) can be used with `add`, `restore`, | `reset`, `log`. It helps a lot with commit hygiene. | | - Most complex rebase are easier to do with `--interactive` | (`-i`). | | - Activate `rerere` in your git config (it will reduce conflict | merges during rebases). | girishso wrote: | This seems like a very good idea. Only if we can scroll through | the commit hashes and see the preview of commit with help of fzf | or something similar, it will be totally awesome. | max_hammer wrote: | I use maggit and can scroll commit log using `ll` | | You can also try `lazygit` it's a TUI written in Go | zhynn wrote: | I have been using lazygit for about six months, and I love | it. | arxanas wrote: | I would like to add fzf-style interfaces to checking out more | things. Hopefully, they could index both the commit message and | the commit contents when searching. | sombremesa wrote: | > Here's my theory: novice and intermediate users would | significantly improve their understanding and efficacy with Git | if they weren't afraid of making mistakes. | | Here's something that happens when people are encouraged to make | more mistakes: they make more mistakes. | | The piece where people are encouraged to _learn_ from these | mistakes is missing from the author 's equation. Without that, | this tool becomes a crutch at best, and a disaster waiting to | happen at worst. | | Can we do better? | | *Edit*: Let me answer my own question. We can do better - for | example - simply by adding the Git commands this program would | run, aside from the human readable explanation. Not sure what | people replying to this comment were aiming for, since they | clearly did not offer up a single suggestion. | | Let me go a bit further and add that self-righteous soapboxes are | NOT a good thing, and as it stands none of the replies to this | comment were relevant. I was hoping to spark a discussion of what | else could be done to improve the experience, but I could have | worded my comment better. | | On the other hand, you can do better. | yoz-y wrote: | I wouldn't be so harsh. I don't know a single program that was | made worse by adding undo. Imagine a painting program without | it. (I'm sure there are some artistic programs that do that but | those would be mostly toys) | | Trying to learn from mistakes that can be solved by an undo on | local repository are mostly in the realm of "be more careful", | which is an impossible requirement to achieve in general. | shadowgovt wrote: | The cost of adding undo is usually the cost itself (i.e. | every operation the program can do must now be considered for | its reversibility). Not every program justifies that cost, | but I have also never seen a program that was made worse by | adding it. | petters wrote: | The tool prints what it is going to do in a nice format. That | is an opportunity for learning. | deeviant wrote: | If your suggestion for making software better is to make | mistakes so punishing that users are thusly properly | conditioned to not repeat the mistake then... may I never use | software you work on. | | An analogy in my mind is a "hardcore"(where your in-game | character permanently dies if you die once) mode in a game. On | the surface, even it's name suggests that a really die hard | power gamer is going to want to try this mode, the phrase | beckons truly a true epic gamer experience that will test the | players skill to the utmost. But, you don't get that. You get | people getting level 2 by killing only level 1 critters for 10 | hours straight (or equivalent), you get a boring, sterile, slow | progressing gameplay that is exactly opposite of what one might | imagine going into it. | Filligree wrote: | > An analogy in my mind is a "hardcore"(where your in-game | character permanently dies if you die once) mode in a game. | On the surface, even it's name suggests that a really die | hard power gamer is going to want to try this mode, the | phrase beckons truly a true epic gamer experience that will | test the players skill to the utmost. But, you don't get | that. You get people getting level 2 by killing only level 1 | critters for 10 hours straight (or equivalent), you get a | boring, sterile, slow progressing gameplay that is exactly | opposite of what one might imagine going into it. | | Well, yes and no. | | Try combining it with a speedrun. You'll find you have to | take calculated risks, and this can indeed add another level | to the game. | deeviant wrote: | Yes, agreed. | | I wasn't meaning to be dismissive of those that enjoy or | make use of these types of game modes, but really just | invoking how hardcore mode ends up on average with the | average user for analogy only. | burnished wrote: | Making a mistake is an opportunity to grow by testing and | validating your mental model of a system. If the price of a | mistake is too high that is the same as saying the price of | testing is too high. If you want to craft a world in which | people can learn more from fewer mistakes then I think that is | a laudable goal but here it sounds like you simply want to keep | that high cost. Side note; Factorio is a game where the price | of making a mistake in your build is having to pick a thing up | and try again. Very low friction for most mistakes. People | learn a lot in that game by making mistakes, myself included | (two direction trains leads you down a path of evil by the | way), and I think if you were to include friction into that | system to prevent them from wanting to make mistakes at all the | overall learning would go down. | | Or for an entirely different example, are you also opposed to | FPGAs? Should people be forced to not simulate circuits before | sending them off to be fabricated, in the hopes that by making | the mistake more painful they won't make as many? | | Besides its not like people need more examples in their lives | of situations where a mistake is not easily recoverable from. | | So to answer your question; I certainly can't, I am a mistake | based learner. If you can do better then please, please, do. | handrous wrote: | Making it possible to "play" safely is maybe the best way to | help people learn. | onion2k wrote: | _Without that, this tool becomes a crutch at best, and a | disaster waiting to happen at worst._ | | The underlying assumption here is that undo features make | people bad at thinking. I suspect that might be true in a lot | of cases, but I think we should give users the benefit of the | doubt and start by believing that they're undoing something | that they tried to reason about and made a mistake with rather | than thinking they're just whacking in random commands hoping | to hit the right one. The outcome might be the same but one is | a little more kind. | | However, a reasonable counter argument to that whole idea is | that without an escape hatch giving users a sense of safety | they'll never even _try_ to use any features that they perceive | as 'dangerous'. Not having the ability to roll back something | they've tried means they won't try, and that keeps _most_ git | users from becoming experts. An undo feature is an immensely | useful learning tool (so long as it always works as expected), | which is exactly what you want if you think that people should | be encouraged to learn. | _jal wrote: | Perhaps it should have been stated outright, but the operative | theory appears to be that if mistakes cost less, making more of | them _becomes_ the learning exercise. | [deleted] | saiojd wrote: | Great work. I wish usability/ergonomy was taken more seriously | for popular tools that everyone uses (like git). Another stupid | pain point with git is the inability to commit empty directories. | I mean, come on. | cerved wrote: | Git takes stability and extensibility seriously. Your demands | and expectations on version control may be radically different | from mine. | | Empty directories do not contain files or information, it's | entirely reasonable for a VCS to omit such a feature. Not sure | which use case for git is hindered by the inability to check-in | empty directories. I would even suggest such a use-case may be | a case of DIW | rileymat2 wrote: | The use case it frustrates me in is when you want to work on | the structure of the repository before you have all the code. | | For instance, it is nice to think about the repo holistically | sometimes before I have say an actual unit test to put in the | directory, it is nice to create that structure in the repo. | cerved wrote: | I see. But then why the record that structure in the index? | Isn't it enough to have it remain in the working directory? | Or if you need it in the index, just the canonical empty | .gitignore? | workethics wrote: | I feel like an outcast after reading all the comments here. I've | never really had issues using git. I didn't realize so many | people had trouble with it. | rexyg wrote: | I can't wait to start using this | caseydm wrote: | This is a great idea. There are well-documented ways to undo | things on stack overflow, but almost every way: | | 1. Has three competing ways available to complete the 'undo' | | 2. Every way has a scary caveat that the user must be aware of | | It would be awesome to simplify the process for new users. | windowojji wrote: | `hg` literally already has `hg undo` as a command. It's good that | `git` can have a similar tool | gldnspud wrote: | While GitUp is a GUI app, and only available for macOS, I think | it's worth noting that it has some great undo/redo capabilities | built in. | | From what I understand, some of them were more feasible to | develop because they implemented their own plumbing (GitUpKit), | instead of relying on the official git plumbing. | | https://gitup.co/ | dilap wrote: | GitUp is such a great app & fantastic UI design, but the author | gave up on it at maybe 80% of functionality, and I think for | that reason (among perhaps others), it never really caught on. | (It's open source and there are still occasional commits, but | it doesn't seem to be really actively worked.) | | Nevertheless my main daily driver, along w/ the command line. | It's undo capabilities, best-in-class visualization of the | timeline, and ability to easily visually edit, reworder, and | squash commits remain amazing. | | (I was disappointed to see newer git clients like Submlime | Merge did not take inspiration from GitUp.) | | Ultimately I think the future of VC will be something patch- | based (pijul?) w/ a UI along the lines of GitUp. | jahnu wrote: | An ex-colleague of mine used to maintain a fork here. Maybe | you could encourage him to continue :) | | https://github.com/douglashill/GitUp/releases | swisspol wrote: | Hey I didn't gave up on it at 80% functionality ;) It had | 100% for my needs and it's been rock stable since then - I | still use it daily! | | But yes, I wasn't really worth _actively_ maintaining it as | it was feature complete and I didn 't intend to build a | business out of it. | dilap wrote: | Yes, I also use it daily, so thanks for making an amazing | tool! | | 100% vs 80% is of course going to be subjective, but the | missing 20% in my opinion is built-in merging and a built- | in repo browser. When I've tried to advocate GitUp to my | coworkers, those are the two things that keep them going | back to SourceTree or Fork. | | (Also, on our (admittedly, pretty large) repos, it's not | quite rock-solid; staging can be unusably slow (requiring | fallback to the command line), switching to the commit view | from the map view can be slow, and making lots of changes | to the working tree will crash GitUp.) | | Still, a brilliant piece of software, and I am suprised | that (1) it didn't find a larger audience and (2) that it | wasn't more influential on clients that came after, like | Sublime Merge. | skrebbel wrote: | Wow, I'm absolutely blown away, this is what I want a Git UI to | be. | | But I'm not on Mac, does anyone know of a tool that has a | similar design idea behind it that works on Windows or Linux? | arxanas wrote: | Nice, this is really cool. Similarly, I had to implement extra | plumbing on top of Git to make snapshotting possible. I'll | update the blog post with a reference. | swisspol wrote: | GitUp uses libgit2 under the hood. GitUpKit is an Obj-C | wrapper I wrote at the time to make it much easier to use. | | Unlimited undo / redo is achieved by taking a snapshot of the | entire repo before and after any operation (e.g. checking out | the repo or creating a branch etc...). The inspiration I had | at the time was that is it is trivially cheap to take such | snapshots: essentially all you need is a list of all the | refs. | | Then when you need to undo, you have 3 things: 1 - current | state of all the refs in the repo 2 - state of all the refs | from the before snapshot 3 - state of all the refs from the | after snapshot Compute the delta between 3 -> 2 and apply on | top of 1. | | The same technique allows to do the Time Machine feature. ___________________________________________________________________ (page generated 2021-06-21 23:00 UTC)