Hacker News new | past | comments | ask | show | jobs | submit login
Git-sim: Visually simulate Git operations in your own repos (initialcommit.com)
447 points by todsacerdoti on Jan 22, 2023 | hide | past | favorite | 180 comments



This looks promising as a teaching aide. At my previous company, I transitioned our project from Clearcase to Git to save us licensing and administration fees. Many of the senior developers, who had never used Git, had a hard time understanding it, and I spent many whiteboard sessions explaining by drawing similar graphs. This would give those developers more autonomy, and stop the “let me blow it away and start over”, which would drive me nuts. Devs spent a lot of time and frustration performing that operation.

I believe the core issue is devs like above never take the time to “grok” Git. I believe part of this is due to the lack of a tool like above to teach easily, but also because devs want to ignore the “how” of their tool working to find out the exact commands they need to run in their current situation.

One could argue users should not need to understand how their tool works to use it effectively and this is a leaky abstraction. Others could argue some commands are not intuitive (git reset can do many things, and git rebase swapping ours/theirs comes to mind). I don’t claim Git is perfect, and sometimes I need to Google to learn more than I wanted to, to get out of an obscure scenario (e.g. someone put classified intelligence into a repository we need to transfer to a lower classification network; how do I rewrite the entire history while correcting this error that occurred 487 commits ago?). However, understanding the tree structure of Git, what git rebase does under the covers, what branches and tags are, how remotes work, how merging works, etc. would go a LONG way. The folk I worked with struggled to pick it up.


> I believe the core issue is devs like above never take the time to “grok” Git.

The problem I have with git us that it's just too complicated. When I'm juggling project complexities and design complexities and implementation complexities, I frequently don't want to have to deal with git too.

I understand how to stage and check in and squash, and branch and merge, and how to manage remotes. But last week I still managed to get a new repo into a state where I couldn't push local changes to github without doing a pull first, and I couldn't do a pull without (apparently) first updating the remote. I had a hard deadline and ended up deleting the repo and starting fresh. Nothing much was lost. I never had this trouble with tfs...

Maybe I'm just not clever enough, but I've never come across a dev tool with as much surface complexity as git.

(Not a git hater. Use it every day. Have had a personal github profile for a decade. Etc etc.)


I've resigned myself to accepting git because I have to use it. But JFC, I've hated it from the first time I tried it.

We now have a large selection of tools that allow you to visualize what's going on (I use git-kraken), as well as google for help on doing something that isn't in muscle memory.

But, really, SO MUCH pain and suffering could have been resolved by refactoring the damn commands to something more coherent and consistent. Git people sometimes call this "porcelain"-- which I guess is an apt name because it makes one think of a toilet (but an improvement to a hole in the ground).


> We now have a large selection of tools that allow you to visualize what's going on (I use git-kraken), as well as google for help on doing something that isn't in muscle memory.

Git Kraken is excellent, though Git has a page on various GUIs, many of which are free with no restrictions: https://git-scm.com/downloads/guis

Personally, on Windows I like SourceTree: https://www.sourcetreeapp.com/

Some that have worked with SVN back in the day like TortoiseGit: https://tortoisegit.org/

On *nix Git Cola seems to do the job for me: https://git-cola.github.io/

Then again, the most complex workflow I've worked with was Git Flow and I didn't need anything more advanced than that. Come to think of it, I don't really do rebases often either and mostly just take advantage of squashing commits through GitLab/Gitea and such, when needed. But hey, that's also valid, using Git in a way where you get version control but mostly keep the technical details out of your way (though Git LFS and certain cases with particular line endings being needed does make you drop down occasionally).


Seconded. Git, like Linux is used everywhere, you can't avoid them. And even though I use it externally locally I use subversion, whose commands make a lot more sense to me. But Linus has something going for him: he knows how to establish critical mass for his projects, and how to create viable ecosystems.


i am no apologetic for the messy git UI. But i also know that any competent software engineer can be given a sufficient understanding / mental model of the basic git way of doing things in 1-2 hours, after which they can Google for the exact syntax of the commands they need (if they are doing complicated things). i feel that if they are unwilling to invest even that much time, then they are going to waste an eternity on endless tools and GUIs.

it's like tar or rsync or ffmpeg. Yes, it's hard to keep track of all the command line flags etc. but thanks to the internet we don't need to. it's far more useful to understand the underlying concepts.


Git is intrinsically a graph model. It's well-suited for very rich and effective visual representations.

If the cli "matched up" with a visual way of thinking, for many of us, the cli would become second nature. But it just doesn't match up. It's fugly and needlessly hard to remember and become fluent in at least for us "incompetent" engineers who already have too much to work on.


And how do you KNOW this? My experiences-- and many other's experiences have suggested otherwise.

Also it's foolish to suggest that one of the 21st century's most complex repository management software is just like tar, or rsync. What planet are you from?


This is maybe the most cogent version of my exact feelings on git I’ve ever read. In theory, I have no issues with git! In practice, the UX is often very very bad.


I teach git professionally. I have a 3-day 12-hour course I give.

I'm amazed how many people who have used SVN or CVS just assume git works like that but with different commands. And, of course, they get very screwed up. (GitHub contributes to this problem, too, with their own set of commands like "forks" and "pull requests" that aren't really a part of git.)

One you understand the Merkle DAG that's at the heart of git, understanding the rest is simple. Yes the commands are named badly, but get past that and it's a great system.


These days, with more young people developing, it's less CVS assumptions as such and more a Frankenstein of cargo-culted CVS assumptions they got at a remove from the Internet and Github's truly awful and confusing web interfaces.

You can't even get a simple gitk-style graph visualization on Github. Which is a website. After so many years, I really think all the blame for developer confusion can be laid at Github's feet.


There's been a graph visualization in GitHub for a long time, they've just intentionally buried it. Currently: Insights tab > Network

Arguably they buried it because it isn't actually what people want when they are looking for commit information. I know I've confused many developers by showing them gitk. I've been slowly working on a hypothesis that "subway diagrams" of commits look fantastic (Git Kraken looks great in screenshots) but get in the way of actually getting work done, much less thinking about the git DAG as an important tool beyond just "visualizing branches". (At this point I keep threatening to build a --first-parent based drill-down UI, that would look ugly as all get out in screenshots but might be a joy to actually use, but so far no one has sent me the check to make good on that threat.)


I wondered if someone would mention that this time around; it is a really bad piece of slow javascript that shows completely whacked-out graphs though, because it is trying to show the "fork" feature from github (and doing a poor job), not really the gitk or log --graph output of anything.

Yes, first-parent and expand would be a good way to view history. Github is a website and should be providing new and interesting ways to view information, not failing to provide even the basic lowest-common-denominator view (the gitk view).


12 hour days? That seems way too long. How did the participants handle the amount of information over the time period?


No! It's 12 hours over 3 days.


Apologies for misreading. That makes much more sense


It is not outside the realm of possibility that Github itself had a problem. I've seen instances where "git fetch" pulls refs but not the objects pointed to by the refs, then it gets cleared up an hour later and my builds suddenly start working again.

It's almost pure happenstance that Linus's idea of Git being distributed lent itself to the Cloud hosting business model. And the hardest thing to teach is the mental mapping of local and remote refs.

So this isn't just Git being too complicated. It's a confluence of several factors that would never have been possible if Git had never happned.


One thing to remember is that a pull is fetch + merge. I always fetch first which doesn't change any local branches. If that doesn't work fix your remotes. You can always recreate your local branches to track remotes, then reset to specific git hashes (if you take note of them or give them temp branch names).


You're not alone. Git is an embarrassment to our profession.


No, it isn't. It's just a tool designed to work with complex software development workflows, which 90% of software projects do not need. 8 commands (pull, fetch, merge, push, add, commit, checkout and branch) are all you need to get going for git, which is like 2-3 more than what you need for svn/cvs. It's like getting upset that cars that are manual have an extra pedal (clutch) compared to automatic cars with their 2 (brake, accelerator).


Why does any serious workflow require you to be in the middle of an interactive rebase all the time?


Huh? You only rebase when you're either:

* Trying to shorten commit history

* Trying to merge feature branches together (main or other feature branches)

* Trying to remove feature branches

None of which are necessary in a lot of development models. If you have that many feature branches that you have to rebase constantly, it doesn't sound like feature branches as a concept are properly understood.

The idea behind feature branching is one of 2 models:

1) either the main branch always works, and development is done in a feature branch, only to be rebased into main when development, testing, and sign off occurred, or

2) serious bug fixes occur outside the main branch, to be re-incorporated back into the main branch once it's been proven to be effective.

The 1st model should only require a rebase when the feature is complete. The 2nd model MAY require a couple of rebasing, dependent on how extensive the bug fixes are, and how fast the main branch is moving along, but not to the point where constant interactively rebasing your branches is the norm.


If you're writing a local stack of commits, you need to do an interactive rebase to edit the commits in the middle. You can't just check out and amend earlier commits in the stack, since git has a branch-first rather than commit-first model (one of its biggest UI failures).


No, I don't. Again, this seems to be a personal design/preference rather than a behavior git is forcing upon you, which is my point (This isn't a git issue, this is a development workflow that seems needlessly over complicated). When I do development locally, I only commit changes I want to keep. If there is something wrong, or code that needs to be modified, I make those changes, and then commit. When the work is done, if pressed upon me by the team, I rebase the local commits to a single commit before submitting a merge request.


It's the same development workflow used by the Linux kernel? You know? The project that Git was invented for?


There are tons of different workflows used by Linux Kernel maintainers. Some of them don’t even use Git except to submit patches.

Whose workflow are you trying to emulate? (followup question: and why?)


Are you working on something as complex as the Linux kernel?


None of my serious workflows require rebases, much less interactive ones.

Not that I don't do interactive rebases sometimes in local branches, but that I absolutely do not make them a part of any more general workflows. I rather try to avoid rewriting shared history where I can, and I'm happy with DAG navigation tools like --first-parent.


How do you manage stacks of commits for code review? (I'm guessing you just don't -- a lot of git users have really messy, unprofessional repository histories. The fact that git doesn't have great tooling for history management is also an embarrassment to our profession)


As I stated in the comment you are replying to:

> Not that I don't do interactive rebases sometimes in local branches

I don't have a problem with rebasing in local branches before code review. I just don't allow rebasing once a branch has started code review, and I especially don't allow rebasing in a public integration branch ever.

(I also rarely feel the need to rebase, personally, even in my own local branches. Working in better tools than git in a past life has given me a lot of the discipline I feel that I need to build good commits as I work. I make much more use of the git staging area than I see most devs generally do and use `git add --patch` and `git add --interactive` far more than `git rebase`. `git add --patch` especially is an under-sung hero that I think a lot of junior developers should learn well in advance of rebase.)

Also, I'm just not that bothered by messy histories in code reviews when I review other developers work. If the idea comes across even if the commit messages don't have the greatest narrative flow or are perfect, I'm perfectly fine with that. I make sure all merges are --no-ff and after that I can browse a "clean" history post code reviews with DAG traversal tools such as --first-parent. But that also gives me an opportunity to dig back into the mess months or years later after the code review if I need to research a bug or a regression. That sort of "sewage archeology" isn't "fun" by any means, but the number of problems I've been able to solve with it is high enough I appreciate keeping that mess around in source control. It's source control's job to keep the mess for me and present me pretty views for more regular work. That's why I prefer to trust tools like --no-ff and --first-parent over --squash, because that's what source control is built to do, control old histories messy or not.


What can I say. You're locked into a significantly worse maximum than is possible (and exists) using better tools. In a normal workflow your commits are small enough that you don't have to do "sewage archeology".


I don't think you are reading me correctly. That is a rare occurrence, but it is possible when using merge commits to correctly describe the DAG. It's entirely impossible if you overly rebase/squash. Those rare times that I've needed to do it it have "saved" a project a lot of time from a major bug or regression. My normal workflow I look at a "clean" faux linear view, but it's just the "--first-parent" view of merge commits, which gives me a "PR focused" or "integration focused" view of source control first.


If your average commit size is 30-40 lines of code, this isn't an issue. Stacks of small commits is a time-tested workflow, used by the Linux kernel among many other projects.


I think we are talking about different things at this point, but I may be losing the thread of your argument here.

I love a code review to consist of lots of small commits. I'm mostly fine if even some of them from developers more junior than me are just named "commit" if they are small.

When I finish the code review I prefer to only `git merge --no-ff`. All those small commits stay in the code history in the exact form they were reviewed under.

If I'm looking at history I'm most often using something like `git log --first-parent`. In my --no-ff integration branch that just shows me an integrated change list (PR list). Git gives me a "straight line" view down the DAG and hides irrelevant information I don't want in that moment like all the small "commit" commits.

If for some reason I find a bug or issue in some code, I may need to drill down into specific small commits including the "commit" commits, and I have that ability because all those commits are still in the DAG.


Finally someone comes out and says it - I totally agree. I don't recall ever having to have a "tutorial" on Subversion. Git solves a problem the average dev really doesn't have in the first place.


It was painfully difficult to branch in subversion. And remember the agony of asking someone to check in a file so another developer can check it out?


Branching was just a copy? What was so hard about that?

As for check-out locks. you only had to ask them to do that if they'd requested a lock on the file which was not the default. I hope people weren't doing that too often at your workplace.


Merging is an operation which takes three inputs: left, right, and common ancestor. This is a very old algorithm, the diff3 utility on Unix is at least from the 70s I think? The reason history is a graph is to walk the graph and find common ancestors. Subversion's model cannot do this (screw off, pedants, I know they added an attempt at detecting common ancestors after Git had long since supplanted Subversion in relevance).

And if you can't merge, you can't branch. And if you can't branch, you need locks.


I'm just saying, as someone who has used subversion quite a lot over the years, the situation he is describing where you have an exclusive lock where they have to check in before you can, does not happen. Exclusive locks are very rarely used in subversion. If you and your coworker are working on a file, and he checks in before you, you will simply have to update and merge. Similar to if you were both working on a local git or mercurial tree.


Oh, and in that situation the 3 way merge is between the version he checked into the repo, your local version you are trying to commit, and your parent revision.


Well put! And it demonstrates why people (like the HN'ers who think they're 10xers) have trouble with git. They fundamentally don't understand the problem and how git solves it.


This is correct, and yet Git is an embarrassment to our profession. That's how bad it is.


To be fair, Subversion had plenty of serious limitations. Local commits are a really good thing. It's just that Git itself is a terrible UI around a bunch of decent ideas.


Sure. Absolutely but there were some benefits to its simple model that are still attractive for a corporate env.

https://www.bitquabit.com/post/unorthodocs-abandon-your-dvcs...

One of my fav rants on this subject.


Mercurial should have won, it's superior in every way. For pesonal projects I use Fossil, which is fantastic.


I organized the migration from CVS -> Mercurial at my last job, and finally after several years when it became clear Git was where industry was headed we switched from Mercurial -> Git. After resisting it for a long time and then being forced to use it for a collaborative project with another firm, I have to say git is way better at being a DVCS than Mercurial.

I think, as other have mentioned, that once you truly "grok" git you begin to understand the elegance and simplicity of the system and how its layered. Ultimately git's use of branch pointers was a way better solution than encoding branch data in the commit itself. To it's credit Mercurial did attempt to rectify this later with bookmarks, but ultimately DVCSs are about branch management, and git has always excelled at it.


Mercurial's branch management makes more sense. If you want to know which branch a commit originated from in git, good luck.

Many things in git, are frankly anti-patterns in any other sane versioning system - comitting partial changesets because of the index? gross. Rewriting history and force pushing? absolutely insane.

The fact that I don't have to "grok" mercurial like you need to git is actually a plus. Mercurial can do everything that git does (and more: check out changeset evolution in mercurial, it blows anything you can do with git rebase out of the water) and it doesn't require Ph.D. level knowledge in directed acyclic graphs to do it either.


> Mercurial's branch management makes more sense. If you want to know which branch a commit originated from in git, good luck.

`git merge --no-ff former-branch` by default includes "former-branch" in the auto-generated merge commit name. When it matters what branch a commit "originated" on, it's very easy to use `--no-ff` (which doesn't rewrite history and won't need any sort of force push!) and most PR tools used to default to that before "rebase" and "squash merge" became some people's favorites because of some weird (in some cases OCD) wish to see SVN-like straight lines only in their commit history.


It isn't a "weird ... wish", a linear history is the correct default. Merges have always been, and should continue to be, a tool of last resort. In general it is good to minimize complexity in life.


Merges are the default state of life in any source control system with more than one person or machine involved. They are a regular, required need. Sweeping them under the rug, pretending that they don't happen, acting like they are rare is exactly the sorts of things that added complexity to systems such as CVS, SVN, TFS, Perforce and much more. It is exactly what adds complexity to so many of these rebase-only and squash-only workflows people like to constantly post about using in git.

Linear history is a punchline that ignores the reality of source control. The only truly "linear" history I'm aware of in source control is systems built on patch theory/operational transforms/CRDTs and that form of linear is subject to reordering and still needs explicit merge commits with (implicit) multi-commit dependencies even if there are few stated needs to visualize that as a DAG.

I agree with you, in general it is good to minimize complexity in life, which I why I eliminate rebase workflows and squash merges from mine. I prefer to see the evidence of where merges happened (and they should happen early and often), and graph data structures are very familiar to me as a software developer, including traversing them. (And git offers useful traversal tools such as --first-parent for when you want to view the DAG more like a linear history and ignore some of the noise. There's no reason to artificially simplify the DAG when DAG traversal is easy and accurate.)


> I believe the core issue is devs like above never take the time to “grok” Git. I believe part of this is due to the lack of a tool like above to teach easily, but also because devs want to ignore the “how” of their tool working to find out the exact commands they need to run in their current situation.

Github is largely to "blame" for this. It mostly only exposes the happy path and using git kind of like any other VCS, but above all it ossifies the idea of git repositories being centralized (both because the canonical repo is always on github.com but also because of the forking/ownership model). A lot of the power (and sharp edges, and messiness) of git are in scenarios where everybody has a local repo and nobody's is really "canonical".

Git is really well-suited to development of the linux kernel. It's not.. amazingly well-suited for the job that 95% of people these days press it into?


I think that the bigger problem is the misuse of Tags as the sole method of marking a commit for release for example.

Tags could be utilised for naming commits which would make it much easier to reason about where in the process of your development you are instead of referencing commits by hash. Hashes are hard to remember after all.


Mutable names should be branches, in my opinion, but not because I think tags are only for releases. I will absolutely use local-only "light weight" tags to name immutable points in time that look nothing like releases (and try not to push them accidentally; this is something that I think git's UI could be better about, it's an expected pattern which is why `git push --tags` or `git push --follow-tags` is a separate action by default from normal push, but `git push --tags` which is mostly all-or-none is much more convenient than patterns that push individual, specific tags). I just feel strongly if it is a mutable reference point it needs to be a branch.

Branches are so cheap in git that there's little to no reason to not use a million branches to name every step in a process if you need to, and yeah if you need a long-term name for a specific commit local-only lightweight tags are handy for that. (I find lightweight versus annotated an often easy enough distinction between tags intended for local development and tags intended for release markers. This also seems to be intentional in git UX because of the way `git describe` by default skips lightweight tags.)


Except, if you rebase, your tags get "lost" (not really, but they still point to the same old commit unless explicitly changed). Log is your friend, and making sure that the commits make sense (they do a single well-defined thing) helps a lot, because you always know which commit does what. But yes, that means using `git commit --fixup <commit id> && git -i --autosquash <commit id>^1` frequently to fix existing (older) commits instead of making new trivial ones.


why are you rebasing a branch that has tags?

in my opinion (the one where i don't care what anyone else thinks kind) you shouldn't be using tags on your working branches and your mainline/release branches should only be the ones where tags exists.

This then means that the only place you should be rebasing is your working/feature/pr branches and that when you merge your working/feature/pr branch, it should get squashed into the target branch... No one cares about your fifty gazillion 'wip' commits.


I guess that's the parent's annoyance. It'd be nice to be able to use something like tags or labels for other things than releases, but since they're commit referents, they're pretty much only useful for releases and nothing else.


I was responding to GPs idea to "name" commits with tags, so you've taken my comment out of context.


This is called a branch in Git.


Why not use branches for that? That's often for people to it.


I agree with your position. Our use case at the company I mentioned above was ten developers, all physically co-located, actually all operating on the same 3 or 4 servers. A centralized VCS was a better fit to our development needs. In situations where the problem space is centralized, applying a distributed tool is using the wrong tool for the job.


> I believe the core issue is devs like above never take the time to “grok” Git

I believe the same, and it's not just a problem you see with git, it's all over the place. Some developers seems eager to use something so they just skim the documentation in order to do the least amount of reading and understanding in order to implement something, but often miss some fundamental detail and have to jump back. Or, they fundamentally misunderstand the tool at all, but push forward with their own idea what the tool is, rather than stepping back and start learning again.


You say that like it's bad, but that's just life. We're trying to fit a whole universe into 3 pounds of meat. If we stopped to truly understand anything before taking action, we'd never get anywhere.

That's especially true in technology, where whole armies of people are working to complicate things as fast as possible. For the best of reasons, of course. But when I started out, I could read one short book and have a pretty good understanding of my computer's processor, and from there it wasn't much further to understanding the whole computer. Now I could spend days just understanding, say, processor cache strategies [1]. A field that is super interesting, but if I am to get any of my actual work done, I can't afford to dig into that and the many, many other similar subtopics. I'm going to get a casual understanding of something, do my best to make something useful, and only dig in further when I'm forced to.

When I do have to dig in, it comes in two cases for me. One is where there is something necessary complexity that I would have to learn about regardless. E.g., if something is too slow, I need to learn about what happens under the hood to do proper performance tuning. Great, fine, I will learn it.

But then there's the other bucket, which includes unnecessary complexity, bad abstractions, poorly considered UX, and the like. For me, git is clearly in that bucket. I intentionally have very simple development flows. Git can do a great deal, 98% of which I not only don't need, I actively don't want. [2] So I'm going do my best to remain ignorant of its inner workings, stick with my small number of commands, and very occasionally refer to "Oh Shit, Git!?!" [3] And I'm perfectly happy with that until it gets replaced with a technology that better matches the domain.

[1] e.g.: https://chipsandcheese.com/2022/05/21/igpu-cache-setups-comp...

[2] An example of what I don't want: https://www.tiktok.com/t/ZTRpPPuKf/

[3] https://ohshitgit.com/


I'm very happy to fundamentally misunderstand GIT's internals because I want to do a finite (and small) set of operations with it, not HOW it operates under the covers.

Conflating the two, like you do, is elitism.

"If you just stopped and read to understand...", a-ha, sure, I'll do that for every one of the no less than 500 tools I've used over the course of my career and will never get anything done on time.

There's no time. We got real work to do and no we can't switch to a company that gives us this time. There's a big world outside the Silicon Valley.

GIT is a huge UX failure and seeing people pretend otherwise makes me question my -- or their -- sanity.


You won't have to put your entire life on break in order to understand the fundamentals of git and why it works the way it works. Going through https://jwiegley.github.io/git-from-the-bottom-up/ and really understanding the material will take you a couple of hours at max, but will save you a lot of time in the future.

Wanting to understand things before using them is hardly elitism, not sure why you would think that.

Just like you probably don't want to fix bugs without understand the cause, it's hard to use a tool correctly unless you know how the tool works.


Git is one (egregious) example though; Do I need to understand the fundamentals of every tool that I use/interact with every day? That's just not feasible. If not, where do you draw the line? To many, git is a means to an end, in the same way that $(insert_internal_tool_here) is. Nobody expects you to know the details of a B-tree and an R-tree to use MySql, so why is it ok to expect people understand the implementation details of git to use centralized version control?


Except not knowing about btrees for MySQL will likely mean you don't understand how to write good indices.


I like your analogy because it outlines the flaw of GIT: we have to "fix bugs" in its UX so we can get our job done with it. :\

Also yeah, I agree learning GIT is not a huge sacrifice but with time I built a huge internal resistance against it so... dunno. ¯\_(ツ)_/¯

Maybe I'll get to it one day, in the meantime I am OK relearning cherry-pick and a few others every time I need them. I don't know, it just doesn't make sense to me. Guess to this day I don't see why it had to be a graph DB.


This article contains some very dangerous advice. In particular it says that the difference between reset--hard and checkout is merely down to the working tree changes not being preserved. What it does not mention is that reset will obliterate commit history subsequent to the requested revision 5f1bc85.

From the source:

Here’s me being straight up loco and resetting the head of my working tree to a particular commit:

  $ git reset --hard 5f1bc85
The –hard option says to erase all changes currently in my working tree, whether they’ve been registered for a checkin or not (more will be said about this command later). A safer way to do the same thing is by using checkout:

  $ git checkout 5f1bc85
The difference here is that changed files in my working tree are preserved.


> reset will obliterate commit history subsequent to the requested revision 5f1bc85.

It's not obliterated. It is still in the reflog, and in the history of any other branches or tags then have those commits in their history.

You have to try quite hard or wait 2 months to obliterate something that was committed or stashed into a repo.

You can even recover changes that were only staged.

Compare this to most other programs (word processors, GIMP, etc) which will happily genuinely obliterate if you undo multiple times and then do anything other than immediately redo.


This language is, IMO, damaging to the professionalism and image of software engineering. IIRC, I am echoing content from "Clean Coder", but in "professional" careers, it is expected that the practitioner is competent and stays up-to-date on the latest tools and techniques in their field.

When I see a doctor, I expect them to be familiar with the latest medical research. I expect they will treat my illnesses with modern medicines and employ the right tools, correctly, and understand how they work at a sufficient level of depth to do the job correctly. For example, I used to make electrical medical staplers; surgeons need not care about how RTOSes work, but they need to know how to interact with the software enough to do their job. Similarly, I'm not saying we all ought to be able to build Git from scratch. I'm saying we ought to master it to the extent necessary. If your use case is committing alone on a single branch, learn "git commit". But for most devs, understanding the tree structure that Git uses to store data and what basic operations are doing "under the covers" builds a mental model that makes Git easy.

We have to have the time to learn the tools that help us do our jobs well. You can neglect that duty to do "real work", as much as a doctor can neglect learning how to use a scalpel so they can "get on with the surgery".


> it is expected that the practitioner is competent and stays up-to-date on the latest tools and techniques in their field.

Even when the tools themselves suck?

The thing about our profession is that anyone can build better tools. Just like Linus took a week or two to sketch Git with some C code and a bunch of shell scripts (seriously, that was what happened - but he had the BitKeeper design in mind and how to improve on it). There is not regulation that says that in order to build a tool for millions of people to use you need to have a certification or anything.


Actually, I believe a deliberate goal was to write something distinctly different from how BitKeeper operated.


Yes, but without being informed by the BitKeeper's design and shortcomings he would never design Git so quickly


We all know the ideal theory, man.

Citing it as if it's something that's even needed to be said is kind of ironic on a forum with mostly programmers in it who, I am pretty sure, by and large possess a fair amount of critical thinking and quick analysis skills.

A ton of people have to make do with partial schedules. And I mean a ton, likely no less than 85% of all programmers everywhere.

You might want to make a good deep analysis on whether you're not coming from a position of severe privilege and a very positive filter bubble.


I agree with you, but I also have the thought of "well, git is one of the _top_ tools of the 500 I use," so I think I'm a bit more inclined to fill in a few more gaps as I encounter them. Ultimately though if you have the right balance of knowledge about the tool, you can always stop learning more about it until you learn otherwise…


Also true, and I agree. As mentioned in a sibling comment, with time I kind of started loathing the idea of learning GIT's internals so here we are. We'll see, these things tend to fall away with time.


[flagged]


The only one complaining here is you. Also this is not Reddit, chill.


You can either learn the tools of the trade, or you can go online and complain about how your hammer is too hard to use and so you refuse to hold it right. How is that not complaining?


You tell the guy using a brick as hammer that it isn’t actually a good hammer, no matter how many other people are also using bricks as terrible hammers. Git is a brick.


Memories of the "PHP Is A Fractal of Bad Design" article...


That's not a good analogy. A better analogy is someone telling you that you need to understand material sciences to be able to use an impact driver properly.


Can you learn material sciences in an afternoon of minimal effort?


No, and you can't learn git in an afternoon either. Here's a very very simple scenario. You and I are working on a fork of a project. You make a branch and push it. I want to update an unrelated branch with the changes from the fork, so I follow [0] (note all of the various adjustments in the comments), and suddenly git switch doesn't work for your branch anymore.

Git has dozens of failure modes like this where the behaviour is completely unintuitive unless you understand the internals of git.

[0] https://stackoverflow.com/questions/7244321/how-do-i-update-...


Not sure what you're going on about. I tried replicating what you describe, but `git switch` keeps working just fine.

    ~/tmp/foo git init repo1
    Initialized empty Git repository in /home/user/tmp/foo/repo1/.git/
    ~/tmp/foo cd repo1
    tmp/foo/repo1 ‹master› echo hi > hi
    tmp/foo/repo1 ‹master› git add hi
    tmp/foo/repo1 ‹master*› git commit -m hi
    [master (root-commit) d0cf572] hi
    1 file changed, 1 insertion(+)
    create mode 100644 hi
    tmp/foo/repo1 ‹master› cd ..
    ~/tmp/foo git clone repo1 repo2
    Cloning into 'repo2'...
    done.
    ~/tmp/foo cd repo1
    tmp/foo/repo1 ‹master› echo hi2 > hi 
    tmp/foo/repo1 ‹master*› git add hi
    tmp/foo/repo1 ‹master*› git commit -m hi2
    [master 3a82bdc] hi2
    1 file changed, 1 insertion(+), 1 deletion(-)
    tmp/foo/repo1 ‹master› git checkout -b someotherbranch
    Switched to a new branch 'someotherbranch'
    tmp/foo/repo1 ‹someotherbranch› git 
    tmp/foo/repo1 ‹someotherbranch› echo otherchange > otherchange
    tmp/foo/repo1 ‹someotherbranch› git add otherchange 
    tmp/foo/repo1 ‹someotherbranch*› git commit -m "otherchange"
    [someotherbranch 99ec880] otherchange
    1 file changed, 1 insertion(+)
    create mode 100644 otherchange
    tmp/foo/repo1 ‹someotherbranch› cd ../repo2
    tmp/foo/repo2 ‹master› git remote add upstream ../repo1 
    tmp/foo/repo2 ‹master› git fetch upstream
    remote: Enumerating objects: 8, done.
    remote: Counting objects: 100% (8/8), done.
    remote: Compressing objects: 100% (3/3), done.
    remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
    Unpacking objects: 100% (6/6), 448 bytes | 448.00 KiB/s, done.
    From ../repo1
    * [new branch]      master          -> upstream/master
    * [new branch]      someotherbranch -> upstream/someotherbranch
    tmp/foo/repo2 ‹master› git checkout master
    Already on 'master'
    Your branch is up to date with 'origin/master'.
    tmp/foo/repo2 ‹master› git rebase upstream/master
    Successfully rebased and updated refs/heads/master.
    tmp/foo/repo2 ‹master› git switch someotherbranch
    branch 'someotherbranch' set up to track 'upstream/someotherbranch'.
    Switched to a new branch 'someotherbranch'


GIT can't be learned quickly by everyone. I for example haven't needed a graph DB even once throughout a 21 years of career.


No, and neither can one learn git in an afternoon.


Speak for yourself.


We speak for more than one person and you should stop pretending otherwise.

Obviously not everyone can learn it quickly. That's a fact. Denying it is ruining the forum discourse.


Mercurial.

Also, not having another option would hardly make git optimal (or even good).


No, it doesn't. It does make learning it practical considering it's what everyone uses.

If you think you can do better, please do! Let me know when you've gotten a few projects to switch over and I'll gladly learn that, too. Not a lot of projects using mercurial these days.


How many projects/companies do you need? There's still a fair number using it.


Practically speaking, anything mainstream that I actually use. And the "still" qualifier there is the problem. That number should be growing, not shrinking.


Ok. Mainstream... you use it.. How about: nginx, sudo, pypy, mozilla/firefox, facebook?

And. totally agreed, the number should be growing (especially for such a nice piece of tech with a far better toolset). Now that you've signed on to learning, hopefully that will be the case.


Serious Stockholm syndrome on display


It's insane to me how many developers simply refuse to read documentation or spend any time at all learning the new tools they're supposed to use.


This is all Stockholm syndrome. Git has a lot of random accidental complexity, from reset and checkout doing too many things (yes I'm aware of switch and restore), to stacks being a pain to work with. The idea that you're supposed to just be in the middle of an interactive rebase most of the time is mind-boggling.

A better thing to say is "yeah we've been saddled with this horrible tool, yeah we know it sucks, but it'll suck a bit less when you learn it. Oh and sorry if you're not a professional developer and have to use git, I hope we can do better next time."


Yes, we all know it has some rough edges and could be more convenient. Unless someone actually makes that idyllic more convenient tool and it becomes widespread, none of that matters. We're stuck with the hammer that everyone else is using. No sense refusing to learn how to use it just because you're stubborn, everyone else managed just fine.


Well no, that's not the case. In fact many projects (gitless for example) clearly show that a consistent UI for git is possible, but unless git developers decide to rework the tool completely, we are stuck with what we have. And no, using a 3rd party tool and convincing every team that gitless is better is simply not going to happen. The way out is for someone to swallow their pride, admit they did a half-assed job and fix it. Not holding my breath though.

I say that as someone who uses git daily, who has learned git internals, who uses cli almost exclusively, who helps the teammates out of their git problems and who still hates the cli inconsistencies.


How to tell apart the professionals from those who just do the equivalent of button mashing to get something to work.


I've seen this phenomenon as well. I've noticed a few factors that I hypothesize contribute to this:

1) Making Computer Science programs in universities overly simple. When I was in college, I tutored students in CS. When I started college, the CS 101 course was taught in Java, and when I finished, it was being taught in Python. There was an immense gap between the understanding of the Python-first vs. Java-first students.

The Java-first students understood fundamental concepts like arrays, passing parameters by reference vs. by value, "OOP" concepts, and other common paradigms in languages. The Python-first students would use "lists" and "dictionaries" for many problems without understanding that those structures impacted the time complexity of their solutions, or that they used memory allocation, reallocation, hashing, etc. Python is great for hacking together a non-fault-tolerant program that does X as quickly as possible, but I saw it damage the way the students thought about computing.

It made the students think it ought to be easy. It made them think that they should be able to write, in nearly plain English, what they wanted the computer to do, and that it ought to do it. It made them think they should be able to intuitively be able to code without spending any amount of time learning the craft, and that they could do anything an advanced programmer could do by typing a few lines of simple code. They were less willing to accept that sometimes problems are hard, sometimes they would have to think, and sometimes they would have to write more than a for loop to solve problems. The Java students' problem sets covered implementation of data structures and complex applications, while the Python students struggled to put together even the implementation.

For a humorous and broader explanation of this subject, see James Mickens' excellent article The Night Watch [0]. For example: "That being said, if you find yourself drinking a martini and writing programs in garbage-collected, object-oriented Esperanto, be aware that the only reason that the Esperanto runtime works is because there are systems people who have exchanged any hope of losing their virginity for the exciting opportunity to think about hex numbers and their relationships with the operating system, the hardware, and ancient blood rituals that Bjarne Stroustrup performed at Stonehenge."

2) Bad documentation, and bad users of documentation. I dislike documentation that neglects how the tool works and instead creates a cookbook that its users can copy verbatim. It has similar effects to what I described above. Developers that use this type of documentation find themselves helpless when they encounter a problem they've not memorized the solution to. I think it also creates a learned helplessness wherein users cannot question the model the tool uses or think outside that model to solve complex problems. I prefer documentation that teaches the ethos of the subject in question so that I can understand better and imagine new solutions.

I've also heard the complaint that Git's documentation is awful; some say that it is only useful if you know already know where what you are looking for is, and useless if not. In other words, it lacks an "apropos" (aka "man -k") equivalent. This is my gripe with "wiki" style documentation. It is scattered and unsearchable and has no cohesion. We as developers need to do a better job creating documentation that is searchable, coherent, and useful to new and experienced users alike. Various sections of documentation should have ample cross-references to help users understand the connection between parts of the system to help them form a mental model of how tooling works.

[0]: https://www.usenix.org/system/files/1311_05-08_mickens.pdf


Git is an amazing tool with terrible UX. It's very difficult to know what the right thing to do is and the mental model is a bit weird. For example, undoing an operation is another, new commit.


That is the option of last resort, when you have already pushed _and_ you cannot mess with the history anymore. The other one being reseting your local branch to a previous commit and force pushing if needed.

Edit: wording


Ahem, let's avoid the over-generalisation thanks!

I learned git at 45yo after many years using ClearCase (even licensed as CC admin) and .. I really liked learning git, I do admit that it took me two full days of self study to start groking git but I wouldn't call it 'struggling'.

Obviously it depends a lot of your background.. git is the 5th version controls I've used , while it is far from being perfect (submodules.. :-( ), it's my favourite.


Were you trying to teach them with the CLI though? That's a terrible approach. The CLI is awful and Git is a visual thing.

It's like teaching someone to drive a car using LOGO.

The way to teach Git is:

1. Explain the mental model (correctly). Basically a commit is a snapshot with deduplication to avoid huge file sizes.

2. Show them how to use a good Git GUI. There are a lot of bad ones. I would recommend Git Extensions (terrible name but it's actually quite good). Or maybe GitX on Mac.

3. Let them learn the CLI slowly in their own time.


I never found a GUI that was more intuitive than the CLI, personally. I am a bad person to consult for this, since I live in vim and tmux (my coworkers hid my mouse for April Fool’s Day and I went the day without it to make a point) while others blaze ahead in VS Code and know the bare minimum command line to get their job done.

I’ll take a look at Git Extensions, thanks for the recommendation! Some of our devs took to using the integration with VS Code, which I didn’t like because I didn’t understand how its terminology (e.g. “sync” mapped to underlying Git operations). Others tried the Git GUI which I found very confusing.

I focused on the graphical operations and then tried to show them what commands they could run to execute those operations. Next time I’m in the situation, maybe I’ll adopt a GUI-first approach.


My issue with gui is that sometimes I need to work with git in terminal, over ssh, so I need to know it. Once I learned it, what's the point of using a gui? [0]

[0] there is one operation where gui is more convenient for me - exploring branches in gui or GitLab ("repository -> graph") has no equivalent in cli that I know of (interestingly, GitHub doesn't have that either, but many gui tools do).


> Once I learned it, what's the point of using a gui?

The first point is that it makes it easier to learn the concept of Git, which is most of the difficulty. Yes Git's CLI is really terrible, but if you know the concepts you can mostly just google the CLI options and learn through repetition.

The second point is that GUIs make it easier to see the state of the repo. There's a reason that even the CLI includes a basic GUI. Don't tell me you never use `git log --oneline --decorate=all --graph`.


I don't, but I'll try it, thanks! TIL. :)


The problem is that every git UI I've tried of the past ~10 years abstracts core concepts in order to (try to) simplify things, then people make a mess and don't have the slightest clue why or how to fix it.

The git CLI for the vast majority of things isn't difficult once you have a basic understanding of DVCS. 95% of the time fetch, pull, push, checkout and commit are all you need.

I admit that Hg had a far nicer an more consistent CLI, and it was my preference back in the day. But it lost for a few reasons - one of which was that it made the 90% easier, but the 10% far harder.


Terrible advice, you should absolutely start with the official UI, which is the CLI. Avoiding it because "it's hard" will just complicate everything down the line.


When teaching children to read do you give them Encyclopedia Britannica? Of course not.


I'd hope developers learning Git are a little more capable than literal children.


I wasn't saying otherwise. It's an analogy. In case you struggle with those, in non-analogy form it would be "Do you start teaching a new concept using its most advanced incarnation?" No, you start from the basics.


Yes much agree!

A big reason I wanted to pursue this idea is exactly what you mentioned - a lack of ability to easily create presentation-quality Git structures that can apply specifically to the situation a user is in, NOW.

A super annoying thing about troubleshooting Git issues is when you find a similar solution online but it's done in someone's random repo which could be very different that yours. Your whiteboard sessions are another good example down this line of thought.


More like a backed-up abstraction, simpler on the inside.

Though that's only true of the core, with tags being additional decorations and renames inferred. The simple core delegates complexity.

I think designing a nicer git UX is not easy. Even if we oversimplify commit to cp your working directory together with a path to the previous commit (to form a tree of "branches"), then the abstraction for operations like rebase to manipulate that tree is not quite intrinsically simple.

BTW Tools can be used without proper understanding, like arithmetic without commuting, associating or distributing. While a workable pidgin aids adoption, it's fair to argue for the power of understanding, especially of something clean and coherent and whole. Git's core is like that; the add-ons (like tags) aren't; and the UX seems arbitrary and accreted.


My company is currently transitioning from a 20+ year old Perforce depot to a git workflow. We're certainly having issues like you describe, where people don't know (and don't care to learn) the mechanics of git. And I agree, git is the kind of tool where once you understand the primitives, you can quickly start making lateral leaps to solve problems.

But I do think that there's room for a better mechanism for orchestrating "macros" or building other workflows on top of git. I know a lot of developers who'd love the ability to pretend they're using p4.


My company wanted to "script away" all the "pain" of using Git to make it equivalent to Clearcase. I think it's a smell. If you want to use Clearcase, use Clearcase. etc.


I don't think that's necessarily a bad thing. Using scripts to change how devs interact with git is just putting a new porcelain on the plumbing.


Except you now have a set of tools without proper documentation and no way of googlng issues. And chances are you created a new leaky abstraction.


This is why I'm in love with Mercurial. It has a very simple mental model which is not far from Git, but Mercurial's commands and presentation are so much more comprehensible.


You can give https://github.com/martinvonz/jj a try. It works with git repos. Jj is developed, in part, by a few Mercurial developers.


Every time I see a thread like this I echo the same sentiments. It’s not hard to grok how hg works, git adds more mental cycles which just take away from solving the actual problem at hand


I want to pile on here; I switched to Mercurial for some projects and didn't think much of it (had to look up equivalents of some git commands here and there). However, after 2 years of that, coming back to git made me feel like a total newbie. I recently got myself into a detached HEAD state and felt like I was groping in the dark with "git reset". I never had this issue with mercurial, even with weird botched evolve/content-divergent states.


Issues with mercurial like that just throw python stack traces at you and say good luck. mercurial isn't good enough to be special from everyone else using git. it's like using your own keyboard layout, of course you can. but there's a cost for not really a good reason.


I used Mercurial at work for over 5 years and never once had a stack trace.

The fact you mention it in reaction to a Git detached HEAD suggests you think that is an error condition / bug in Git. Although I hate Git, I know it well enough to know that a detached HEAD is not a bug and it can even be useful sometimes. Or maybe you're referring to half-finished rebases - those exist in Git too. If you did think these are bugs in Git then I think that proves how confusing Git is!

Git won over Mercurial because (1) it was released before Mercurial (by a fairly short margin), (2) it was written by Linus and that's a level of celebrity to devs that is hard to beat, and (3) it's the basis of GitHub (partly because of 1 and 2). If the top open source hosting service were HgHub, or Git had been written by some other developer, things could well be different. (But now that we're in this situation, I agree it's better to use Git like everyone else even though it's an inferior tool.)


Nice I need to find some time to actually sit down with Mercurial for a nice summer afternoon


Do you know of a GitHub equivalent for Mercurial? Bitbucket no longer supports hg. :/


There's also Heptapod: https://heptapod.net/

> Heptapod is a community driven effort to bring Mercurial SCM support to GitLab™, started by Octobus, a company providing professional services around Mercurial.


There's sourcehut, though it's quite a paradigm shift from github.


I really like git. I like teaching it to my fellow developers, I frequenty use git cherry-pick, git rebase, multiple remotes, submodules, ontop of the usual "common" git stuff.

I found GitExtensions (windows) which I used at my last job to be VERY useful, as it is git, properly, the way it was designed, but in GUI format. It taught me a lot about how to actually use git.

Now I dont use the GUI, its too slow to click around when I know the command.

I dont get the git hate. Then again, I also dont get the "C++ is too complex/complicated" debate, either, so maybe I just have a higher tolerance for terrible design.

Or maybe git just is a very powerful tool and takes more than half a year of half-assed use to learn.

Teaching some basic things like rebase vs. merge, how to git bisect, how to pull with rebase, update a branch with rebase before merging it, stashing changes, etc. got me and the team I lead at $CURRENT_WORKPLACE very, very far.

I can recommend to stop complaining about git, find someone who knows how to use it, and just ask until you get it. Its worth it


> Or maybe git just is a very powerful tool and takes more than half a year of half-assed use to learn.

And also distributed version control is complicated. Git isn't as intuitive on the happy paths as perhaps it could have been and shows its slightly rushed initial development, but no tool that allows such flexibility can ever be truly simple. And in its defense, it wasn't originally designed to be a super-simple glossy tool. The technical advantages of it simply outweighed the slightly clunky interface, and that interface has improved since then.

I do recommend to use the "git lola" alias to give an easy gestalt of the repo state if you're ever unsure what's going on.


It doesn't matter how much I look at them, and I get the reasoning, but the right->left flow orientation of VCS diagrams will always be disorienting for me.


You can use the --reverse flag to reverse the direction of the graphs in Git-Sim.

However the fact that time flows in the opposite direction of the parent/child relationships, is inevitable based on Git's design.


I always have to remind myself that they’re dependency arrows and not a sequence ordering.

They make it look like it flows right to left even though time (or at least sequence) flows left to right.


Suggestions;

    1. In the static output, put a dashed, or shadowed marker corresponding "frame 0" of the animation, e.g. in the git reset example, show where "HEAD" was before (perhaps even add an arrow)

    2. Make it possible to 'remember' a set progress, of git commands - and replay them. (I.e. simulation looks ok, now apply them on real git)

    3. Make it possible to visualize actual git log in the same style as simulation.


This is really good!

I generally have a good mental model of my repo and I try to KISS as much as possible, but I can see the value of this in a teaching scenario, for example (as well as on extremely complex git situations).

Check out the quickstart page as well, seems to have more content[1].

[1] https://initialcommit.com/tools/git-sim


Haha wow you posted this before I could! I created Git-Sim and hope that folks can get some use and value out of it. Happy to answer any questions anyone might have, and especially looking for feedback so that I can improve the tool. Also if anyone is interested in contributing let me know and also check out the project Github page:

https://github.com/initialcommit-com/git-sim


Its... cool?

Alternative would be: clone the repo, do your changes, run gitk to be sure.

Which has advantage that result looks exactly the same as it will in production (no new diagram type b/c only using git and gitk), with zero risk that sim differs from reality.


Ew clone a repo to simulate a command?!

Hehe jk you make a fair point, and in fact I do have a bunch of work left to do to make sure my simulations do match up with Git's behavior as closely as possible.

One big benefit I was going for with Git-Sim though is to interrupt the developer workflow as little as possible.

Changing directories, running a new clone (which could take a mildly annoying amount of time), and running gitk is a pretty big context-switch.


Looks great!

I'm really missing support for remotes. There are lots of tools for local-only development (like https://gitexercises.fracz.com/), but very few allow to demonstrate stuff like "Syncing a GitHub fork with the original repository" which involves two remotes and three copies of the same branch at the very least.


This is a great point. I thought about how I could simulate commands like "git pull" and "git push", but like you said that would require communicating with the remote to determine ... stuff ... like what objects need to be synched, and potentially even doing some of the actual data transfer before an accurate simulation would be possible.

My initial goals for this tool are to purely simulate actions on Git repos without actually modifying them, but I might be flexible on that going forward, as I mention in the article with the --execute flag.


> simulate actions on Git repos without actually modifying them

One way around this could be to create a new temporary directory in /tmp, copy .git over there and symlink the rest, then run whatever operation in the newly copied workspace and compare it with the original.

Then you can mutate things however you want and the original stays the same.


Hey cool idea! I'll definitely consider that and variations on it. This could work for Pull-direction operations like fetch/pull, but maybe not as well for push since the remote would still be affected in some way.

Will need to think about it more...


You can push to a folder too. So you can just do the same thing. Clone the remote into a folder and push into it.


Was gonna suggest the same! I use this countless of times. It's really cool how you can push/pull to a bunch of different things, including directories, ssh hosts, anything that can act as a directory (network mounted FUSE directories) and more.

Personally I use it a lot for backing up git repositories to a USB stick where I have a backup of every single repository + its branches and commits in case I ever need to recover from them. And I can keep my GitHub remotes clean without 100s of branches.


This looks fantastic!

I think this is what we need more of for new git users. I struggled for the longest with git until I came across learngitbranching[0]. I believe having an interactive/visual experience while I typed in commands is what I needed, and what most people need.

I tell junior developers they should take a day to learn this and more often than not they dismiss me. Meanwhile these people will run into git conflicts or something and their strategy is to "save their work somewhere else and redownload the repo"[1]. I know of a "senior developer" that will do that. I basically told him, in my eyes, if you don't know how to use git, you are not a senior. Or a bad senior at a minimum. See the stack overflow survey. Git is used basically by all developers. How do you expect to be a good developer by dismissing such a ubiquitous tool. I think I can make an exception for people who aren't using git at their current company and any company before.

[0]: https://learngitbranching.js.org/

[1]: https://xkcd.com/1597/


> save their work somewhere else and redownload the repo

Not that there's anything wrong with that, is there?

As a "bad senior developer" who uses git daily, one of the things that I love about git is that in the end everything is regular files. So there's nothing wrong with just copying your git repository elsewhere, re-cloning it, and fixing your fuckup by hand. No need to feel guilty about it.

Your comment sounds like criticizing somebody that does not know all the keyboard shortcuts that you do.


Do you understand how merge conflicts happen in the first place? If you are to be a senior leading others, you should be able to explain this to juniors so they don't shoot themselves in the foot.

Do you disagree that it's a fundamental tool to being a developer(today), or do you disagree that it's necessary to know fundamental developer tools to be a good senior developer?


Ther'es a difference between understanding how merge conflicts happen, and understanding how git handles basic operations in order ot be able to use it effectively.

> If you are to be a senior leading others, you should be able to explain this to juniors so they don't shoot themselves in the foot.

Firstly, not all seniors are managers. Secondly, it is not a good use of a senior engineer's time to be teaching fundamentals to a junior developer. I am a decent developer, a passable manager, and a poor teacher. It's much better for me to point my team in the direction of existing tools.

> Do you disagree that it's a fundamental tool to being a developer(today), or do you disagree that it's necessary to know fundamental developer tools to be a good senior developer?

Other VCS tools exist, it's possible to have gone a decade in the industry as an effective developer without using git. Many large companies use Perforce, other companies use internal tools. I disagree that it's necessary to understand the working model of fundamental tools to use them. We don't require truck drivers to understand the difference between the Otto and Diesel cycles to drive a truck, why is it ok to force developers to undersatnd the many, many, many different operations that `git checkout` can perform depending on the state of your repository/what you've asked it to do?


If you’re a senior at a company that uses git, these are all terrible answers.

As a senior you not only should understand how to stash local changes and handle merge conflicts, but also generally use your VCS to elevate your development ability. Finding who added a bug and when with cherry picking. Retroactivity applying changes to all of history with rebasing and branching. All of this git provides if you put in the effort to learn it, and more. It’s an incredibly powerful tool, and to not use its capabilities is simply a waste.

Your “reclone the repo and start again” case is a lot of wasted effort. You could use one or two quick commands to undo your changes. Your ignorance at how the tool works doesn’t undermine its value or purpose.

I’d expect a senior to not only be able to handle these cases, but also show interesting other tools in git and when they’re useful. I wouldn’t expect a senior to not be able to handle simple conflict resolution.


Git isn't the only version control tool widely used, and I've handled hundred+file merge conflicts with other VCS tools before, with significantly more ease than the same conflicts in git.

> but also generally use your VCS to elevate your development ability.

You're moving the goalposts here.

> Finding who added a bug and when with cherry picking

You've made the assumption that cherry picking is the right way to do it. You do you. Meanwhile, for the 3 times a year it matters when it was introduced, I'll just use the history view of my IDE.

> Retroactivity applying changes to all of history with rebasing and branching.

Im firmly in the "version control should be an immutable ledger of what actually happened" camp, but the reason you need to modify history with git is a design decision that everyone needs to be familiar with. Imagine if you told people "hey you need to know the implementation details of transactions in mysql to write a select statement?"

> Your “reclone the repo and start again” case is a lot of wasted effort

Tóg go bog é - you're putting words in my mouth here. Nowhere have I said that reclone and start again is acceptable. I'm saying it's unacceptable that you need a working understanding of the design model and implementation details of git to use it even remotely effectively, and that it's a poorly designed UX around a very powerful tool.

> d expect a senior to not only be able to handle these cases, but also show interesting other tools in git and when they’re useful. I wouldn’t expect a senior to not be able to handle simple conflict resolution.

We expect fresh grads to handle merge conflicts - part of our onboarding requires you to make a change and handle the conflict we enforce with it.

We don't expect everyone on the team to understand the details and reasons around why detached heads exist to be able to develop, or to understand the intricacies of a DVCS to review a coworkers change, and yet I distinctly remember the conversation with my lead a few years ago when he asked me "how do I checkout the branch you've just pushed" which led to this madness [0]. This was the example that stood out to me, but over the years there have been countless things like this (submodules, LFS, checkout vs branch, git commit vs git commit foo.js, reset; all have absolutely wild footguns).

[0] https://stackoverflow.com/questions/1783405/how-do-i-check-o...


If you work with git, you should be proficient with git. All of your points are dancing around the fact that your main point is that “being sloppy with git is OK because I don’t know it and it’s not like what I like using”.

And no, I’m not “shifting goalposts”. A senior should be able to use their VCS to elevate their development powers. I wouldn’t expect a junior to know that, but I would expect them to learn it from seniors and in their practice.


Because most problems like merging and resolving correctly, or rebasing or squashing if needed don't get resolved by cloning a new repo. If you avoid learning the tool and you just clone a new repo when you have a problem you won't be able to do any non-trivial task in git.


Thanks for checking it out!

Would be great to get any feedback you might have if you get the chance to install/test it out.


Will do!


Pretty cool!

One idea I really like for avoiding VCS operation anxiety for beginners and experts alike is a filesystem layer that allows revert to any historical state. You just have your bash prompt output the current snapshot number, and then can use that as the revert target if there's a botched rebase or so. Unfortunately I do not know of a nicely packaged way to do this, or how to do it at all with OSS tools (but I bet it is feasible!).


> You just have your bash prompt output the current snapshot number, and then can use that as the revert target if there's a botched rebase or so.

That is what the ref-log is designed to do, but in my experience with git the risk is not about getting historical content, because git is very good about that: it's the current operation that's the risk

If I had any advice for beginners, it'd be to commit early and often, because git is disciplined about managing commits, but is a razor blade about anything in the working copy. There is no ref-log for "but I just typed that..." unless you told git to save it in something with a sha


Yeah, but ref-log is scary to beginners (I suppose rebase is too!). Rebase was a poor example, but even so, it is way easier to copy a snapshot number out of your cli and restore than it is to dig through your reflog for the right sha

ref-log doesn't save you in so many situations. As you point out, you have to commit all the time for it to save you. Even then, git repo corruption is possible and then you are hosed.

For example:

* a hard reset clears your working copy changes

* you pop a stash you didn't mean to, atop your working copy changes. Now your working copy changes are intermixed with the stash and you have to manually decouple them.

* you accidentally stage hunks to your index and its tricky to unstage them because they are adjacent to other hunks

Such a tool also saves you from accidentally saving over your work in the text editor. It generally makes it so that you don't need to be as careful.

So, generally, git commands that affect your working copy are not undo-able and can be very time consuming to undo if you have no proper time machine underneath your repo. I happily have experienced the bliss of having this reassurance, but it is only within a proprietary env.


I've had VCS operation anxiety since the days of CVS. With Subversion it was largely a non-issue but Git made it return with a vengeance. This tool will presumably calm my frayed nerves.


If your fs already supports snapshots/versioning it might be convenient, but it doesn't solve the actual hard part which generally comes after changes have been merged upstream.

If we're only concerned with local changes I'd rather introduce beginners to `reset`, experts will already be doing something similar dependent on circumstance.

    git reset --hard

    git tag BEFORE
    git reset --hard BEFORE

    git reset --hard ORIG_HEAD

    git reflog
    git reset --hard HEAD@{<N>}


You could also use VM snapshots to undo any damage during the learning process.

Ironic, I know.


The animation would be clearer if there was also an annotation of what was happening at each moment.


Interesting thought - do you mean like a line of text that displayed above that verbally described what's happening?

I was considering adding some more detailed text-based output on the command-line detailing what was going on, but I didn't think about adding it directly into the image/video.


I think it would be helpful in the blog post to list the series of changes happening to the files before the animations


Good suggestion, I will add that.


Exactly that. For example, the HEAD tag moving to another commit doesn’t mean much if a developer doesn’t know what HEAD is or what git reset does.


Trying to install it right now and wow it is taking some time. Running 'brew install Pango scipy' is taking more than 5 minutes(still counting). I knows its a one time process but still. The number of dependencies can be reduced I guess.


Hey there fellow Mac user! And thanks for testing it out - were you able to get it installed or is it still chugging along?

Yes I feel your pain with Homebrew which can take forever just to check for updates on installed packages, before it even gets to installing anything new.

I know the current installation method of having to first install Manim's dependencies is not ideal, but in most of my testing it was relatively painless.

However going forward I am going to be looking for ways to make it a single install instead of various steps that differ across platforms.


Yes, i am testing it now.

So far seems good, initially i was getting some very slow animation times but adding the `--low-quality` flag seems to work well.

I am planning to do an internal session in my company on Git, and will be using this tool to help them visualise some of the concepts :)


Sweet! Yeah the slow animation is a Manim performance limitation, I think (hope) their community is working on improving that.

Yes --low-quality works for testing but the fastest way would be to first test without the --animate flag at all, so you just get a final image of the command's effect.

Then once you get that you can add the --animate flag to generate your final video to share.

And awesome to hear it will be used for your company session! I love teaching people about Git. Feel free to share the tool with them so they can try it out as well!


I saw the video and instantly recognized the manim style, it looks great!


Manim rocks.


This is the best tool I'll use once and then never the name of again.


Next HN post - "I destroyed my repo - but it WORKED in Git-Sim!"


I have always wanted something like this. Will be giving this a try. Nice work!


I tried to get manim and its dependencies installed and ran into some issues:

  error: subprocess-exited-with-error

  × Building wheel for manimpango (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [27 lines of output]
      Error in sitecustomize; set PYTHONVERBOSE for traceback:
      AssertionError:
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-13-arm64-cpython-310
      creating build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/_version.py -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/__init__.py -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/utils.py -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/cmanimpango.pxd -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/cairo.pxd -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/register_font.pxd -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/pango.pxd -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/glib.pxd -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/enums.pyx -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/register_font.pyx -> build/lib.macosx-13-arm64-cpython-310/manimpango
      copying manimpango/cmanimpango.pyx -> build/lib.macosx-13-arm64-cpython-310/manimpango
      running build_ext
      building 'manimpango.cmanimpango' extension
      creating build/temp.macosx-13-arm64-cpython-310
      creating build/temp.macosx-13-arm64-cpython-310/manimpango
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX13.sdk -I/opt/homebrew/opt/openssl/include -I/opt/homebrew/Cellar/pango/1.50.12/include/pango-1.0 -I/opt/homebrew/Cellar/harfbuzz/6.0.0_1/include/harfbuzz -I/opt/homebrew/Cellar/pango/1.50.12/include/pango-1.0 -I/opt/homebrew/Cellar/glib/2.74.5/include -I/opt/homebrew/Cellar/fribidi/1.0.12/include/fribidi -I/opt/homebrew/Cellar/harfbuzz/6.0.0_1/include/harfbuzz -I/opt/homebrew/Cellar/graphite2/1.3.14/include -I/opt/homebrew/Cellar/cairo/1.16.0_5/include/cairo -I/opt/homebrew/Cellar/glib/2.74.5/include -I/opt/homebrew/Cellar/glib/2.74.5/include/glib-2.0 -I/opt/homebrew/Cellar/glib/2.74.5/lib/glib-2.0/include -I/opt/homebrew/opt/gettext/include -I/opt/homebrew/Cellar/pcre2/10.42/include -I/opt/homebrew/Cellar/pixman/0.42.2/include/pixman-1 -I/opt/homebrew/Cellar/fontconfig/2.14.1/include -I/opt/homebrew/opt/freetype/include/freetype2 -I/opt/homebrew/Cellar/libpng/1.6.39/include/libpng16 -I/opt/homebrew/Cellar/libxcb/1.15/include -I/opt/homebrew/Cellar/libxrender/0.9.11/include -I/opt/homebrew/Cellar/libxext/1.3.5/include -I/opt/homebrew/Cellar/libx11/1.8.3/include -I/opt/homebrew/Cellar/libxcb/1.15/include -I/opt/homebrew/Cellar/libxau/1.0.11/include -I/opt/homebrew/Cellar/libxdmcp/1.1.4/include -I/opt/homebrew/Cellar/xorgproto/2022.2/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/usr/include/ffi -I/opt/homebrew/Cellar/pango/1.50.12/include/pango-1.0 -I/opt/homebrew/Cellar/harfbuzz/6.0.0_1/include/harfbuzz -I/opt/homebrew/Cellar/pango/1.50.12/include/pango-1.0 -I/opt/homebrew/Cellar/glib/2.74.5/include -I/opt/homebrew/Cellar/fribidi/1.0.12/include/fribidi -I/opt/homebrew/Cellar/cairo/1.16.0_5/include/cairo -I/opt/homebrew/Cellar/pixman/0.42.2/include/pixman-1 -I/opt/homebrew/Cellar/libpng/1.6.39/include/libpng16 -I/opt/homebrew/Cellar/libxcb/1.15/include -I/opt/homebrew/Cellar/libxrender/0.9.11/include -I/opt/homebrew/Cellar/libxext/1.3.5/include -I/opt/homebrew/Cellar/libx11/1.8.3/include -I/opt/homebrew/Cellar/libxcb/1.15/include -I/opt/homebrew/Cellar/libxau/1.0.11/include -I/opt/homebrew/Cellar/libxdmcp/1.1.4/include -I/opt/homebrew/Cellar/glib/2.74.5/include -I/opt/homebrew/Cellar/harfbuzz/6.0.0_1/include/harfbuzz -I/opt/homebrew/Cellar/graphite2/1.3.14/include -I/opt/homebrew/Cellar/glib/2.74.5/include/glib-2.0 -I/opt/homebrew/Cellar/glib/2.74.5/lib/glib-2.0/include -I/opt/homebrew/opt/gettext/include -I/opt/homebrew/Cellar/pcre2/10.42/include -I/opt/homebrew/Cellar/fontconfig/2.14.1/include -I/opt/homebrew/opt/freetype/include/freetype2 -I/opt/homebrew/Cellar/xorgproto/2022.2/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/usr/include/ffi -I/opt/homebrew/opt/python@3.10/Frameworks/Python.framework/Versions/3.10/include/python3.10 -c manimpango/cmanimpango.c -o build/temp.macosx-13-arm64-cpython-310/manimpango/cmanimpango.o
      clang: error: no such file or directory: 'manimpango/cmanimpango.c'
      clang: error: no input files
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for manimpango
  Building wheel for srt (setup.py) ... done
  Created wheel for srt: filename=srt-3.5.2-py3-none-any.whl size=22467 sha256=ef7a967b7b3225064d5e8eecf84934ec066e759d288fcddbe104d26954b1df35
  Stored in directory: /Users/me/Library/Caches/pip/wheels/2b/4a/52/216182e898297499cfe0947127f551712c4169ea2e69bcf9d7
  Successfully built click-default-group srt
  Failed to build manimpango
  ERROR: Could not build wheels for manimpango, which is required to install pyproject.toml-based projects
I'm not sure what the underlying problem is here. Anyone have any ideas?


I installed a later Python with pyenv and was able to get this to work.


Ah good! Glad to hear it. I had some issues when trying to install it on Mac's using the system Python. Switching to a homebrew-installed version of Python >3.7 worked for me in my testing.

But glad you got it working too!


Weirdly, this builds on my Intel mac but not the M1 (same issue). Looking the versions of the deps, I can't find the difference. Python 3.10.9 on both.


- Dear padawan, here is your powerful elegant lightsaber. Yes, it can cut the vegetables you eat on a daily basis. You can even cut your hands easily with it. That's why I'll teach you the art of forecasting most probable outcomes of your next moves when you are using it.

- Thank you Master, finally I see the light and understand the the fork or chopsticks dilemma is a fallacy. Millions of jedi knights can't be wrong after all.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: