Where are my Git UI features from the future?
blog.waleedkhan.name
blog.waleedkhan.name
If you think that a git rebase is overcomplicated, rather than a fundamental primitive, then you missed an important part of the tool. And phrasing it this way is an insult to anyone who really tried to understand the tool - kind of like the nerd badge in schools.
Git rebase is fundamental to Git in many ways. It is also easy in many ways. At the minimum, it makes it easy to make mistakes while experimenting much less of a hassle, since the commit chain can be cleaned up later.
However, the point here is that git rebase is more similar to what the kernel developers and git developers intended to do with the tool, compared to the commit-merge workflow. There are two aspects here:
1. The tool developers want every commit to be feature-complete and that it won't cause broken builds at least in the master branch. This is impossible to achieve in the regular commit-merge workflow.You need to add the interactive rebases to achieve the goal.
2. Git hides something behind the snapshot model it claims to be based on. The commits themselves are snapshots. But the way changes are propagated between commits (like stashing, commit amending, merging, cherry-picking, rebasing, squashing, splitting, etc) depend on plain old text diffs/patches. It takes a while for beginners to realize this. The kernel devs were using emailed patches and tools like quilt patch manager for nearly a decade before they created git. You can still see the influence of diff, diff3, merge and quilt in the design of git. Knowing this makes you much better at predicting the outcome of these operations. Blaming the tool without trying these techniques is very uncharitable indeed.
I've been learning Pijul these days. All those complicated operations are condensed into a small set of commands in pijul. For one, it concentrates on patches only. I feel that part of Git's complexity is its mixing up of snapshot and patch model into a single program. Git didn't have the luxury of these diff alogrithms back then.
I very much subscribe to a "patch-stack" workflow, but have a great deal of difficulty doing advanced things in Git, because `git rebase`/`git rebase -i` do not support enough workflows.
Here's some features I've implemented which improve on `git rebase` in general: https://github.com/arxanas/git-branchless/wiki/Command:-git-...
Wonder if anyone has made a git client that lets you manipulate it at that level. Tree looking graph that allows you to drag connections to where you want them.
I believe you're describing GitUp [1]. I can't really say much about it, though, as I've never used it myself (because it's OSX only).
[1]: https://gitup.co/
https://github.com/git-up/GitUp
> GitUp is built as a thin layer on top of a [Mac-only] reusable generic Git toolkit called "GitUpKit".
I looked this up and Pijul is a "distributed version control system" being written in Rust:
- Worries only about patches, not about snapshots too - Only a few commands to learn. No complex switches - Combines many git approaches in one. For example: - pijul record (its commit) is an interactive code selection at the same time. - Merges and rebases are all the same (due to the way commits are linked)
Another issue is the Nest (our hosting service), I've been working on a new Nest that can benefit from being open source, unlike the current one.
Another indication that it's doing alright: I'll give a talk about it at BOB 2023 (bobkonf.de), and an invited talk in April at Collège de France.
I can't wait until Pijul escapes the nice and grows in popularity.
This seems to be one of the major divisions in SCM users, some see it as a clean up for seeing a understandable 'history', others see it as a falsification.
1. Worked
2. Grabbed a coffee
3. Worked again
You are falsifying history. One commit or more per butt-in-seat mini session.[1] Anything else is borderline fraudulent.
[1] Or per balls-of-feet in front of your standing desk, if that is how you roll.
I take issue with tools that prioritize rebasing, because they usually make this distinction between rebasing a local branch and rebasing a shared branch. For example, GitHub's "Squash and Merge" or "Rebase and Merge" options break the shared history between the remote copy of the repo and my local copy. After such an operation, I cannot merge from main into my development branch, and must instead rebase my development branch onto main.
Some people want to rather merge instead, but in my experience few people have the discipline to develop in large enough PR granularity to make the resulting merge commits meaningful and not polluting history while also keeping the non-merge commits meaningful by doing rebases while the change is still in review.
One is always curating history by deciding when to commit instead of dumping the whole undo tree.
I don't see it as a falsification. I see it as making the history less understandable. Having a track of what happened, can help in understanding what was intended. Code archeology regularly helps me understand Chesterton's fence.
Programmers are human. They make mistakes. The thing is not perfect at the time of squashing. When the inevitable issue crops up in production, I really want all the information I can get.
If you start cleaning stuff up, not only do you deny me information about how the code evolved, you also introduce another point at which a flawed understanding can mislead those that come after you.
Name your commits appropriately and don't commit for every comma.
People learn quickly the lay of the land, if they have to.
You think that lots of tiny commits, each providing an incremental, working improvement to the code is bad practice?
And for your example, if they're measurable improvements you should be able to write a decent commit message.
We don't expect people to give important speeches without writing a draft first, nor do we insist on seeing all their drafts. Why is this any different?
Think of your branch as being one long multi-day math problem. If I'm grading your work, I don't want you to show me all the parts you think are neat and tidy and important after you arrive at what you think is the answer. I want to see everything you tried, even the stuff that didn't work.
I'm not opposed to only having merge commits on master, but somewhere, on some branch which is recorded for all of time, I want to be able to see every decision that was made to bring HEAD to what it is right now, on the most granular level possible.
Yes, a maths teacher wants to see the working to a problem, but the working can still be the second draft, written neatly and well explained. For a complicated problem, it should not be expected that someone will read through all the “scratch work”.
Do people really read through the changelog commit by commit? What's gained by that?
I don't read through it at all. I zoom into a point that I need to know more about. I have information (bug report, runtime behaviour on other data) that allows me to zoom into a specific part. The information I have is from the committer's future. It's highly unlikely that the details needed are in the summary that they wrote.
The main problem is when the programmer who created the squashed commit is no longer around.
That subtle bug they introduced in that squashed commit now has to be picked apart without any context. If I have 10,000 tiny commits (and it's never quite that bad because programmers are lazy gits), I can reconstruct come of the context of how that bug got into the codebase and what was going through their head when it occurred.
The other problem with squashed commits is that nobody will ever agree on what the correct granularity of a squash should be. Even if you give me the ability to squash, I won't. Someone else will squash 1,000 lines of changes, and I'll want to scream.
And, to be fair, even Linux doesn't really like squashed commits at the individual level. Try feeding one of those big squashed patches into most maintainers. They'll tell you to GTFO until you bust that apart.
Instead, every single part of your patch should be in a small standalone commit, as far as I understand it.
If I see some behaviour that changed in a commit that says "lint fixes", I can be pretty sure you didn't intend that. I'm still going to check, but if I don't find anything to give me pause, I'm confident in reversing it.
If I see it in a commit that says "fix edge case", I'm going to check, double check and triple check if that edge case is still resolved after my fix.
The "oops" and "work in progress" things hold no information, but since that's the default, well... Too bad.
A cute little paragraph is almost certainly going to leave out details I need. I'll probably ignore it, because it's either unnecessary verbiage, or inane. Probably both.
Meanwhile if you demand meaningful messages for every tiny commit, you'll be lucky if you get much more than "fix".
Also, I demand nothing, not even a certain commit message. What I ask is that you don't expend effort to destroy information.
I understand the desire to hide one's flaws. To hide the thought process to make yourself look better. But it's not necessary. Everybody has flaws and it's far better to have the thinking in the open, so we can see and work with it.
It is super nice to see if it was 20 code commits and then one test commit, or back and forth between tests and code, or a new test and then code commits.
1. A source code control system which allows you to manage the history and branches of your code. 2. A source code collaboration system that allows you to share code with others.
git rebase is excellent for (1). It could also be considered fundamental to it. I know I certainly use it a ton for this purpose and would find myself lost without it.
Unfortunately git rebase completely breaks (2) and if all git was is (2) it would certainly be considered an anti-feature, if not a bug.
I’m not sure I follow the logic? What is it about rebase that makes sharing difficult? Isn’t rebase just a merge strategy? And if you have code in a branch, and you share that, it doesn’t matter about the merge strategy? Or am I missing knowledge/misunderstanding something?
I’ve only ever used rebase in the very plain and not interactive mode of “please just apply my changes back on top of the incoming upstream changes” which does none of the history rewriting haha.
Why is this impossible to do with a commit-merge workflow? If I do work on a development branch, then merge it into the main branch, only the merge commit appears in the main branch, and that merge commit has the final feature-complete commit. The main branch then has an unbroken sequence of feature-complete commits.
The only two complications are (1) avoiding fast-forward merges with the --no-ff flag and (2) viewing the history using the --first-parent flag. The first ensures that you always have a merge commit, even in cases where the history could be accurately represented without it, and the second avoids display of the development commits.
- Work in progress: My change request has been open for some time; I will rebase it against the master branch.
- Accepting changes into master branch: `git merge` or `rebase + commit` or `rebase + squash + commit`.
I don't think there's any practical downside to rebasing WIP branches.
Some change in the main branch (after your feature branch diverged) could break the new feature, without causing a merge conflict.
(Yes, there probably is some magic switch in git log that reduces the merge commit noise. But approximately nobody knows it, looking how the primary argument for squash+rebase workflow I've seen in teams I worked with was always "because it avoids the Christmas tree/chainsaw and overall denoises the log".)
--
[0] - For example this is a reason I vastly prefer HN and Reddit to phpBB-style boards. I find linear threads to be stupidly bad UX for discussing a topic. I know many people disagree, but I've been participating daily in enough forums of this style, some pretty high-volume ones, that I know what invariably happens is people recreating threading with quote-replies and lots and lots of pointless scrolling.
Comment threads and code history are vastly different things. The latter in the end is always linearized and the merge turds (if present) encode bits of history on the side. The former really are tree-like, and also not about code but about natural language.
The easiest thing in the (git) world to understand is surely the cherry-pick.
Why on Earth do people make such a meal out of rebasing? It's just cherry-picking a bunch of stuff somewhere!
Honestly, try explaining rebasing and merging to someone unfamiliar with git - I think the concept of merging is (not hard but) way harder. Yet for some reason people who are .. well, who use git in their jobs decide rebasing is difficult and unnecessary. I don't get it.
And to 'rebasing as a concept is fine but the UI is annoying', really? I'm sure it could be better, but big deal? I use it multiple times a day and however 'could be better' it is, it's absolutely fine. If it was such a big deal, surely someone would have done it and it would be popular. Know your tools, or learn them!
I think the fundamental issue is that - of all the things I want to be neat and well organized in a codebase, the commit history does not even rank. I just cant bring myself to care.
The way I see it, it's a feature rather than a problem. For once, the name (interactive) agrees with its purpose. Interactive rebases are meant to be manual editors for git history - sort of like how commits are meant to be manual operations. Automatic commits miss the purpose of all the flexibility built into the tool.
> Having to go through a whole interactive rebase because I forgot to link to a bug number in one of the commits is rather annoying. I don't get this. Rebases are cheap if you do it frequently. My rebases typically consists of maximum 2 ops at a time. It's not much more complicated that commits themselves.
> It's also a little annoying that i can't do an autosquash without an interactive revase.
I have never personally seen a use for autosquashes. Others may have the same experience and may be why there is no autosquash. However, it wouldn't be too hard to include if there is a good demand.
My linked git-branchless tool will tell you before a merge conflict occurs, so that you don't have to abort it, although it could produce more information about the impending merge conflict.
In my experience best is to coordinate with other about code changes to avoid conflicts altogether or to fetch and rebase often to keep conflict scope to a minimum so they are more manageable. Also keeping commits focussed on single features/changes instead of spreading out the feature over multiple work in progress like commits so they can be applied as a standalone change helps. I really learned this when working in Gerrit Review for a while. Where there is no one pull request for a branch full of commits, but each commit is a change applied to master on its own and has to be reviewed/tested as such.
Git is not a magical tool that solves all collaborative coding problems, but more a toolset that helps you manages code changes. You definitely need to put some effort into the mental model of how to manage changes before you can use the toolkit to its full potential.
It will let you know in advance if conflicts will occur when merging another branch or revision (by merging, rebasing, or pulling). Here's an example: https://imgur.com/a/VCkqrBI
You can learn more about Tower's Merge Improvements here https://www.git-tower.com/blog/tower-mac-9/#1-merge-improvem...
I hope you give Tower a try!
It is, for me. I love git and checking in my progress in small chunks that make sense to me is very easy with the command line tools. They're also easy to integrate and automated. Maybe they truly are the pinnacle of usability?
As another example, compare cashiers using one of those DOS GUIs with modern ones using touch screens. The simpler GUI works much faster, once mastered.
In my experience, most git users don't really know how git works fundamentally. They just learn the commands for a particular workflow and stick to that. That's how I started. I've seen this to be especially true for developers coming from SVN or another centralized versioning system.
To everyone who says they "don't get" how people could be confused or lost while using git, you are the reason why those folks are lost, and you're perpetuating the culture of elitism by playing dumb.
Git is hard as shit to understand unless you came from development before it existed, or you have had the luxury of trying other VCS professionally. Most people just know git, and it's confusing as hell if you have no reference.
Don't even get me started with how this has poisoned the industry on the whole: Proper VCS implementations with CI/CD are incredibly rare, even at places with world class engineering talent.
1. People who have an organizational development model and workflow which is equivalent in complexity to the Linux kernel development model and workflow (i.e. thousands of developers loosely coordinating the release of systems or mission-critical software on a regular cadence). For them git fits their needs better than almost anything else, and it makes sense because it was made for exactly that use case.
2. People who learned their first VCS after Github had reached critical mass and if you had to pick one VCS to start with, you picked git by default. For them their brain fits git, and they think "the git way" is synonymous with "the right way".
Many folks in group 2 never stop to realize that they are on a development team of 5 (or 50, or 500)...and they always cut their release from `master`...and all of their branches are always pushed/pulled from the same Gitlab remote...and within 5 minutes they can chat with anyone who's made a commit in the last 2 years.
I don't take issue with group 1 people who understand the git model and love it and adopt it in their workflow because they need its complexity and they're willing to pay the UX tax to get it. I take issue with the folks who don't understand the git model or realize they don't need any of the complexity and aren't aware of the existence of solutions like fossil and mercurial.
Personally I use sublime merge or command line for everything. The sublime merge/text interactions are really nice, being able to right click in a diff and have it open the file at the line. You can try them for free forever but the price may be a deterrent since the dark theme for merge is locked behind a license key.
Also, when on command-line, I recently discovered `git add -i` for interactive mode (asks you about individual hunks and lets you "split" them), and `git add -e` (lets you edit the patch however you want).
or by right clicking in the diff pane in git-gui (which is almost never mentioned).
Although I use the cli more, gitk and git-gui solve all my GUI needs.
1. git add -i or -p 2. History edits using interactive rebases 3. Using tools like lazygit or git-ui 4. Using stacked patch tools like stgit or topgit 4. Here is my favourites: Use magit on emacs or fugitive on vim
The last one on magit and fugitive feels like interactive addition is closer to editing 2 files.
I work at Tower and I recently put together a "Tower versus Sourcetree" comparison page (there are many features that Sourcetree is missing): https://www.git-tower.com/compare/sourcetree/
I hope you give Tower a try! :)
Sometimes, it’s not obvious that a thing that’s made it to the main branch (whether committed or merged) is problematic until a while afterwards. In that case, later commits/merges may have been made that mean the problematic one cannot be cleanly reverted (conflicts, whether by accident or because it’s been deliberately built upon).
What I want to be able to do is to revert a commit _and any later commit that depends on it_ - or at least be able to see a graph that shows the dependencies to make a risk/reward trade off between reverting it all and trying to fix the problem manually.
This is definitely something it’s possible to do - I’ve done it by hand too many times!
I just want a single command that will do all the reverts cleanly, and the option to list the necessary reverts instead of doing them.
Well, "rebase -i" will do that if it can be done but that’s unlikely unless your commits have nothing in common.
As changes will be necessary to adapt the code to the removal, it’s kind of hard to tell from the start what will be affected. Things might have knock on effects. It’s funny because I don’t really like Git but this is one of the case where what it does seem to be the best doable considering the actual complexity of the issue.
If you just want to see what will be reverted you can do a three way diff between HEAD, the commit to revert and the commit you intend to revert to btw.
In the simplest possible configuration that exhibits the pattern, there are commits like this … - A - B - C. To revert A cleanly, C must first be reverted because it changes code also changed in A. B touches a different part of the code and so doesn’t need to be reverted.
Factor in a few days worth of commits from a large team, and it’s easy to see how very complex trees (even graphs, I think, so long as all the dependencies point backwards) can appear. But it _is_ always possible to get a minimal ordered chain of clean reverts that are required to revert A and all its dependencies.
It’s definitely true that, as you say, things might have knock-on effects - like, perhaps there no textual dependency from B to A, but the logic is very much dependent. Thorough testing of the results is needed. But in a large well-factored project the chances of things being fine when an entire dependency chain is reverted are (in my experience doing things like this) surprisingly high.
To revert A you want to compare the difference between C and Z (commit before A) to the difference between A and Z so as to see where things which were changed in A will impact what’s in C while reverting so you can see what’s salvageable and what’s not.
To come back to your chain of commits, use "rebase -i", do not pick A, and "rebase —skip" every following conflicts and you will end up in the state you want.
I am not sure I have ever encountered a situation where targeting a single commit to revert would have actually worked(from a rebased merge). I would go as far as saying that git revert should be a nuclear option reserved for only the worst of situations(urgent PE hotfix?). If something is worth reverting and was missed by the engineer and the reviewers, it seems the like fix should also atomically contain the explaination with a test to prove the issue was fixed. Because of this mentality, I believe it has been several years since I have seen a 'revert' in the wild.
Maybe I am alone in the industry with my opinion. However, I have seen the same patterns unfold on many teams. ...A lot of concerns with switching to a dead simple git workflow that fade almost immediately after trying it. Just my experience (backend batch jobs, applications, and rest services).
This is exactly the kind of change I’m talking about - the problem is it’s later discovered to have flaws that the tests did not reveal, but enough time has passed that later changes depend on it.
I am not sure I have ever encountered a situation where targeting a single commit to revert would have actually worked(from a rebased merge).
It almost always worked in my experience. The systems we’ve worked on must be architected differently.
If something is worth reverting and was missed by the engineer and the reviewers, it seems the like fix should also atomically contain the explaination with a test to prove the issue was fixed.
Agreed - the problem comes if the fix is not obvious and a fix cannot immediately be applied. In our workflow, when we have belatedly learned of a problem a change is causing, a revert should then be done to keep the integrity of the main branch.
I should stress that this is an exceptional case - but we did see it a few times a year.
The "git sucks" heading might turn off readers; there are so many "git sucks" articles with less nuance and research than this one. (Notice most of the comments already are just related to that, or git in general.)
Thanks for the feedback. Do you have a better idea for the heading name?
> Notice most of the comments already are just related to that, or git in general.
After having read the comments for many Git-related articles, and having posted a few of my own, I can tell you that this would have happened regardless of how well the article was written :)
This is a pretty lousy aspect of HN and I don't think it's any kind of indication the article is somehow not well written. But I think you underestimate how much these initial conditions affect the quality of discussion.
Git definitely does not suck for me.
reword: sl metaedit <commit>
sync: sl pull && sl rebase -s 'draft()' -d main
split: sl split
preview: not that I’m aware of, though I’ve never looked for it
undo: sl undo
large-load / large-ops: yeah, it was designed for FAANG monorepo-scale
Additionally, some other features that sapling has that I wish git had:
smartlog: Show the state of all my branches off of the master branch, what commits there are, whether they are passing the CI test suite, and whether they’ve been code reviewed: https://sapling-scm.com/docs/overview/smartlog#super-smartlo...
absorb: when you’ve got one commit eg adding a new method, and another commit making use of that method, and you then tweak both bits of code, “absorb” automatically merges your add-method tweaks into the add-method commit and the use-method tweaks into the use-method commit
I’m looking forward to the planned server and sparse options being brought inline with what the internal tools were.
Adding an “undo” command would be convenient, but it would hide the underlying potential away. This is something that should belong to a GUI client, and I still would want to know what is it actually doing.
Instead of hiding the abstractions behind a “friendlier” CLI, Git shows you its real power and that of VCSs in general, by having a lower-level API.
Not even the multiple GUIs built on top of Git, adventure themselves into hiding or dumbing down the abstractions that allow you to do quite complex things with the code and its history.
> Adding an “undo” command would be convenient, but it would hide the underlying potential away.
It would not hide any underlying potential away; see https://blog.waleedkhan.name/git-undo/ for a general-purpose CLI implementation.
But that’s simply not true. Git is just inconsistent in how it does things.
Sometimes it wants you to deal with its inner state (typically the undo where you just need to move HEAD to a previous commit which might be only visible in the reflog). Sometimes it introduces complex concepts which would be simpler if they were just exposed for what they are (stashes are just temporary commits).
Honestly Git is a mess. It works but the UX has always been awful.
Awareness of state is sometimes important, sometimes you just need awareness of operations. And awareness of git's data structure does not necessarily map 1:1 with understanding the state of the code base. Not saying you’re wrong, just saying that this may or may not be a good thing. I’m personally leaning towards this could be improved.
Really good advanced tools should work well for common use cases, so you can master it incrementally. Git is extremely frictionous for certain simple tasks, which is evident if you look at stack overflow. If a user wants to do something very simple in human terms (like fix a typo), and you get a lecture about merkle trees and reflogs, then I think there is room for improvement.
The truly important question though, is whether the UI can be improved enough without changing the data model (ie can replace the UI without replacing your repos).
Another was treating branches as "labels", that can be advanced to a more recent linear commit timeline. Very useful for a production branch following the main dev branch (essentially electing commits as production-ready).
> No one bothers to consider: what are the workflows that people actually want to do? What are the features that would make those workflows easier?
What a coincidence, I just created a document [0] that collects engineering and UX issues that we are running into with inlang (localization infrastructure built on git) [1]. Part of bringing version control to people outside of software engineering is fixing UX related issues.
For example, your proposed `sync` command is interesting. Our observations lean towards some real-time collaboration workflow that could make `pull, push, sync` workflows redundant. Applications that benefit from version control like a next-gen Figma, Adobe Premiere, Excel, etc. require real-time collaboration. A question that I've been asking myself whether real-time collaboration in software engineering makes sense too. To be elaborated! :)
[0] https://github.com/inlang/inlang/blob/main/content/git-sdk-n...
- It is evidently difficult for git GUI front ends to implement truly general purpose undo/redo the way any users expect any other GUI to have. This makes discoverability hard, maybe impossible, with a GUI front end to git.
- Not all git operations map to the "generic operations on a selection" model most GUI software implements. There is no general "do this to that."
- You can create a visualization of a git repo, but that visualization doesn't do a lot for a GUI, because of the lack of a selection or focus.
It all still has to be coordinated in the user's brain, which is why most people end up just having to develop a deep understanding of the git command line. GUIs do not take away much, if any, cognitive load. Imagine having to know how a text editor manipulates the structures representing a document.
It's hard to think of another design domain that is so intractable for GUI interfaces.
As to the specific suggestions, some of them are very poorly thought out. For instance, the proposal for `git reword` suggests you shouldn't need to have the commit checked out since it won't create a merge conflict. Sure, but the SHA will change, and this will change all downstream commits, which means you could potentially be triggering a massive, silent rebase that will blow up spectacularly when you try to push.
Another one is the `git preview`, saying you should be able to predict the conflicts on a rebase. But this is exactly what rebase does already! You start rebasing, then you get a conflict, at that point you can either fix it and proceed or abort the rebase being no worse for wear. Obviously you can't see the subsequent conflicts until you resolve the first, so there's no magic "see all downstream conflicts for the entire operation" possible (if that's what the OA meant, I'm not sure).
Finally, the `git undo` is just a hand-wavy ask for the functionality provided by `git reset`. Combined with `git reflog` you can undo arbitrary operations including ones that you had abandoned and "overwritten". It's an incredibly simple and powerful model. I get that the `git reset` flags are not super intuitive, but they are few, terse, and domain complete.
- git reword: https://github.com/arxanas/git-branchless/wiki/Command:-git-...
- git move will perform the magic "see all downstream conflicts", but unfortunately will only show you the number of conflicting files, at present: https://github.com/arxanas/git-branchless/wiki/Command:-git-...
- You cannot undo arbitrary operations with the reflog (nor with `git reset`). See https://github.com/arxanas/git-branchless/wiki/Architecture#.... Besides those points, my `git undo` can even undo some working copy changes: https://github.com/arxanas/git-branchless/wiki/Command:-git-...
`git rebase` can be started and aborted, but to start it safely, you have to first set aside all of your existing work in the working copy. You can't really run it on the background or in parallel, which makes it annoying to do operations like rebase all branches, and can ruin build caches, which ends up being a significant problem on larger repositories. It's possible for the UI to show an icon next to each of my branches indicating whether they would rebase onto the main branch successfully, but no interfaces at present do (including my own). Or, for example, I should be able to start dragging a branch to indicate a rebase, and the UI should speculatively check which target branches can be rebased onto successfully and indicate that.
It could be simpler and better thought out by removing the unnecessary staging area like mercurial did.
When do you get over the hump? I've been using git for nearly a decade, I understand the internals of its data structures, I can talk about the difference between a rebase and a merge, and I still need to reference a cheat sheet for anything more complex than creating a branch, pulling from head, and committing.
Not sure if this is what everyone wants, but adding a wrapper language around the commands was really powerful for me. Everything could be tab completed, used names and terms that I could remember, and at times the new commands became so baked into my mind I forget at times they are not part of core git.
80% of people are "perpetual intermediates" or beginners, they never get any better than they have to.
And at this point Git is pushed into a lot of environments where a lot of non hard-core hackers are using it.
Reality always wins against idealism and the Git UI sucks.
On a personal level, I use pijul for managing my dotfiles. I haven't encountered any bugs yet. The only feature I miss from git is the availability of tools like syntax highlighters for diff and record and UIs like tig, gitui and magit. But again, those are just features you could add as minor versions. That aside, pijul feels like magic. A handful of pijul commands cover most of the use-cases of git. After using git for so long, I always wonder if I'm using pijul the wrong way, even though I get the expected result. I'm only familiar with svn, git, bzr and hg. Perhaps Darcs would have given a better idea about what pijul really is.
I was thinking of doing a synchronous release of 1.0 along with the new Nest: the current one has a cool architecture (replicated over 3 datacenters, using Pijul repos as CRDTs), but doesn't scale well, I'm working on a serverless version. The hard bit is convincing Pijul that it's talking two a real Pijul repo, whereas it's actually talking to a serverless cloud (that's already solved btw).
EDIT: I also don't think there's a "right" way to use Pijul. The magic of algebra means that you can't possibly break the associativity and commutativity properties of Pijul patches, so you can do whatever you want, I'm sure it's fine.
> I also don't think there's a "right" way to use Pijul. The magic of algebra means that you can't possibly break the associativity and commutativity properties of Pijul patches, so you can do whatever you want, I'm sure it's fine.
There is a certain time to 'internalize' the concepts of a tool like git or pijul. It took me years with Git and I'm only starting to be confident about my git skills recently. I haven't had that much time with pijul and I haven't absorbed its concepts yet. Despite that, pijul feels like a concept that I can learn much faster. That causes this 'sunken cost' fear. If it was so easy to learn a VC tool, why did I take so much time with Git? That's what I meant with that comment.
I'm a big fan of pijul. I even have a plan in a future project to manage editing history using pijul concepts (or library).
I think git is pretty good. It was good enough to be the first VCS to really reach critical mass (before, I used RCS, CVS, SVN, and hg). It might not be the BEST vcs, but it's got everything I need and it's easy enough that I can teach non-technical people to use it and clean up after them when they find the footguns. And the cli has been shortly but surely improving. It has facilitated my collaborations for 15 years with very little misery.
One other nice feature of Sublime Merge is the squashing of two commits, ignoring the latters message (as a fixup). Not sure how to do that in one click or command with cli git…
(I made a test repo to check this, because it had actually never come up before in my day-to-day usage.)
- It has to be an ancestor of `HEAD`, like you said.
- Doing so doesn't invoke Git's `post-rewrite` hook, which can cause interoperability issues with other tools :(
- Doing so will abandon at least some descendant branches (possibly all descendant branches which aren't checked out, or possibly just those which branch aren't ancestors of `HEAD`).
- Doing so doesn't seem to be undoable inside Sublime Merge via the undo command.
What I want in a git gui is first and foremost the fundamentals of my workflow built into the tool.
What patterns for branch names means they are private? Or short lived? Or forked but never merged back? This should control e.g how a graph is drawn (you don’t bend the main branch etc) or how branch pruning is done.
If I push a feature branch, later it’s merged on a server using a as squash commit and deleted remotely, then there is no way to say it should be deleted locally because there is no merge commit. This means something is missing. Either the knowledge of deleted branches should be communicated. Or the record that the branch was pushed to the central repo but is since deleted there must be saved. And this requires also specifying clearly that a remote is the source of truth. Git just doesn’t care. The remote list is basically a map of names to urls. No name is more special than another, just like no branch names are really special. And while flexible, it’s also extremely limiting.
Not having git and using most other VCS (fossil and mercury are pretty good, too) creates way more misery.
> No one bothers to consider: what are the workflows that people actually want to do?
Well, here is where the problem is. Git has some fantastic workflow features that most people don't learn or use (https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). Workflow is also problematic because it is exactly where people will demand a wheel, except for more round, every time.
So... how could it be better? Abstract it away to the os and filesystem so it is just part of the routine. Having full support for versioning everywhere would help because many of the rough edges with git are caused by having to support multiple OSes. A lot of confusion is that you have to use git's own tools or do an add/commit cycle for what should just be os file commands. These issues exist because git is not an OS level tool. Imagine commands like find or grep can return the file and version... imagine being able to just mv \dir;crusty-branch \new-dir and it just works. Back in the day, VMS did primitive versioning and it was quite nice (ie \dir\myfile.txt;22 where 22 was the version). Adding versioning like this also would encourage vendors to have sane file formats, so they could be versioned by the OS and pick up almost free change history features.
Slapping a UI on git isn't all that helpful - many, many users just use git from the ide or command line, anyway. As far as workflow goes, the author has a point that git does not come with a lot of strong opinions or obvious ways to do things out of the box.
Not sure if this is exactly what the author is looking for but I made Autorebase exactly for this.
https://github.com/Timmmm/autorebase
Great article btw. A lot of those things are way harder than they should be.
EDIT: oh, article author is git-branchless author, they know of git-stack.
Don’t get me wrong, VS Code and Github are both okay. I use them both and drop into the integrated terminal for situations where my muscle memory is faster or the workflow is going to be more complex. I also find that setting VS Code to my default editor for Git makes this pretty seamless. Anyway, I find it interesting that there doesn’t seem to be a big focus on the sort of features the author mentioned in VS Code.
Now that I think of it, this is also one of those few circumstances where I don’t need or want the tool to be modular. VCS are such a fixture today that I just expect this to be built into the IDE’s GUI. A separate app, even with perfect workflows, may be just as much of a bother as a terminal. After all, what’s stopping me from writing a handful of clever aliases?
I also know how to do this on the command line, but sometimes I enjoy using a gui on macOS.
As for the features, it:
- supports `undo` of arbitrary operations quite well. - has a dedicated `reword` (as "edit commit message") command/flow (but will ask if you want to stash your current working copy, with the option to automatically re-apply the stash) - `split` kind of works by entering a "edit a commit" flow, which lets you stage and commit multiple times. In short, editing a single commit can generate one or more commits. - `large-ops` and `large-load`: I've never noticed the GUI becoming unresponsive, but it's possible none of the repos I've checked out are large enough.
Note: Tower on Windows feels out place on Windows/ doesn't work as well as on Mac, but is still a formidable git GUI.
Here's an example: https://imgur.com/a/VCkqrBI
More info here: https://www.git-tower.com/blog/tower-mac-9/#1-merge-improvem...
I call this out because I have been using SmartGit as my only git gui now for about 10 years and I think it does a grand job. It doesn't hide any information about the repo and makes just about any operation pretty straightforward. I also find it's built in diff and merge tools better than others. It also performs well enough and had been super stable.
(I am not affiliated with SmartGit, just a happy customer).
EDIT: retract harsh words
I guess I reacted strongly to the negative review because despite your assessment it is still an eminently usable tool and in all the time I've used it haven't needed it to do anything more than it does.
As per my original comment though, I'd you haven't tried it's conflict resolution/merge tool I would recommend you do and perhaps you might be tempted to give it at least half a bonus point :)
Anything beyond the basic stuff gets a refresh clone and that's about it.
I would call the benchmark article rather subjective due to limited amount of comparable features and excluding most frequent workflow components with a respective ease of use score.
Looking at one of the latest changes [1] in which a _new_ merge strategy (ort) was introduced and made default one can ask how is it possible that so fundamental change happened 15 years after git was created?
Maybe the model is not so simple as it wants to seem.
[1] https://github.blog/changelog/2022-09-12-merge-commits-now-c...
What if someone else rewords the same commit?
Overall git does use the filesystem in a lot of cases when it is not needed.
I suppose there is some possibility for merge conflicts in a workflow where you reword a public commit, which changes the merge-base in an unfortunate way and causes conflicts to appear which wouldn't have otherwise. Primarily I meant the workflow where you reword local commits only.
More enlightened version control systems like Mercurial can handle this better, such as via its "commit evolution" feature. If you then rebase on top of a reworded commit, the patches will apply the same, and you can resolve the so-called "divergence" by running `hg evolve`. (It's still possible to have un-automatically-remediable divergences, such as if two people reword the same public commit in different ways, but it handles the common case.)
Except when the commit is already synced to another instance of this repo.
https://www.jetbrains.com/help/idea/edit-project-history.htm...
Resolve Merge Conflicts:
Becoming more productive with Git is one of our main goals, and I'm happy to state that most of the operations you address are already included in Tower (apart from "sync", which we will think about internally).
As for the others you mentioned:
reword - you can edit any commit message from the currently checked out branch by right-clicking the intended commit and selecting "Edit Commit Message"
Example: https://imgur.com/a/kexC8uW
split - you can edit any commit from the currently checked out branch by right-clicking the intended commit and selecting "Edit Commit". You will then be able to reform that revision into one or more new commits.
Example: https://imgur.com/a/NFkT4nS
preview - Tower offers an "Instant Conflict Detection" feature that will let you know in advance if conflicts will occur when merging another branch or revision (by merging, rebasing, or pulling). Our latest major update was focused heavily on creating a better merge experience and you can also see the number of unresolved conflicts that you still need to resolve (with a progress bar being shown in case of a rebase). If you mess things up, you can also undo the latest operation or abort the Merge/Rebase operation altogether.
Example: https://imgur.com/a/VCkqrBI
You can learn more about Tower's Merge Improvements here https://www.git-tower.com/blog/tower-mac-9/#1-merge-improvem...
undo - you can undo pretty much any operation with CMD+Z (or CTRL+Z on Windows). This includes not only commits, branch creation/deletion but also more complex operations like merges, rebases, and even file discards (which is not something Git actually supports).
You can learn more about Tower's Undo here https://www.git-tower.com/features/undo/
large-load - Tower works well with large repos. We do build caches on first run, so the initial run might indeed take longer to display very large sets of data (e.g. 10k+ tags).
large-ops - We designed Tower from the ground up to remain responsive when doing any kind of operation. All commands run asynchronously, so you can e.g. push a branch and immediately checkout another branch simultaneously.
I hope you give Tower a try in the near future — feel free to get in touch with us if some other question pops up.
I think this is uncharitable at best. It was a huge step forward compared to then popular VCSs such as Subversion, I have loved working with Git since it was created and I still enjoy working with it every day.
Of course, Git won for a reason, but I doubt that it wouldn't have still won had it incorporated some UX design ideas from Mercurial or elsewhere.
> I have loved working with Git since it was created and I still enjoy working with it every day.
I have been profoundly frustrated by working with Git every day, hence the article, and the linked set of tools which I wrote to improve my workflow. Not even because its mental model is hard to grasp or that the UI is poor, but because it doesn't even streamline the kinds of workflows that it should be good at (in the article, and discussed in its own `gitworkflows` man page).
1. Linus Torvalds wrote it
2. GitHub
3. Linus Torvalds wrote it
To be fair, there are some real differences; e.g. there is no easy "hg rebase" by design, and whether that's a good or bad thing has been a topic of contention for about 15 years. But that Linus wrote it gave it a huge boost, and GitHub really was much better than many things that came before it (and arguably, still is).
I don't think performance was the main motivator; from what I recall it was mostly that Linus felt that the subversion model was "completely broken" and that there weren't any good distributed "bitkeeper-like" tools out there (and then, suddenly, there were three).
"When we first started working on Mercurial, we found that it was slower than Git in several notable areas. To narrow this performance gap, we’ve contributed over 500 patches to Mercurial over the last year and a half."
https://engineering.fb.com/2014/01/07/core-data/scaling-merc...
Personally I can't recall any serious performance difference after I switched from mercurial (which included some large-ish repos) to git, but it's been quite a few years ago and perhaps I just forgot.
Like the one I use semi often (aliased to re) is "git reset HEAD~1". If you read the Git book, you know what reset does, you know that HEAD is where you currently are, and you know that "~1" means "commit before". So you tell git to reset current tree to commit before the one you're currently on (essentially "undo commit").
Actually, having "git undo" to "revert whatever I just done, regardless of what it was" and "--explain" ("tell me what I am about to do") would probably help a lot...
0.5. it doesn't get in the way of getting things done (at least most of the time)
A lot of the UI simplicity of other tools rests on not doing (3). For example, OP awards negative points for rebase but as far as I am concerned I won't even consider using a UI that doesn't support rebase.
I don't. This is "worse is better" at its core! https://www.jwz.org/doc/worse-is-better.html
Simplicity of implementation prioritised over simplicity of interface can take you a lot further than the other way around, in a fast-changing, experimenting environment.
I do have a bunch of aliases and one added command (shortcut to deleting some stuff) but nothing really more complex that shortening up commonly used stuff.
Mercurial Queues exists and people use(d) it. It has many, many more footguns than Git, and it's shockingly easy to loose work. The fact that this was ever acceptable is interesting.
Phabricator is not good, or at least not as good GitLab, GitHub, or Gerrit (IMO). This is important, because Git alone is half the picture nowadays.
The extensibility of Mercurial is also interesting, and leads to codebase-specific commands. This is maybe good for long-term developers, but makes onboarding new hires just that much harder.
So Mercurial's UX being that much better than Git is - in my very limited experience - a myth.
I started using Mercurial as the first serious DVCS I used (dabbling earlier with things like bzr) and my experience doesn’t support this at all.
I think it’s hard to underestimate the degree to which familiarity skews these assessments, especially with the additional confounding factors of project custom and experience. If you first used Git when contributing to a larger or more complex project than you were used to, it’s easy to misattribute the challenges to the tool and forget that everything got easier with experience using any DVCS.
This is especially true for the not uncommon case where the problem is really that someone has strong opinions about how they think the tool should work and refuses to learn its actual design - I’ve known multiple people who ranted about Git who were also the guys who hacked up their development boxes before saying a project was too hard to install (“Python packaging is terrible!” “Didn’t you use sudo to overwrite /usr/bin/python with Python 3 right before getting all of those Unicode decode errors?”), or, in one notable case, say Debian packaging was broken after they manually upgrade MySQL and somehow managed to render the system unbootable.
The reality is, Git is unintuitive, and makes nearly every common thing the average person wants to do a complete pain in the ass. I understand you (and I) know how to get things done using Git, but as a society and a technically community, we should strive to make things better.
When learning to program, you end up in arcane states. When learning languages, you end up in arcane states. Even when learning how to drive, I ended up in arcane states.
Obviously a bit of hyperbole, but when hopefully when you learn it and end up in weird states, you have a companion helping you to correct course.
From my experience as sysadmin the people having problem with it also highly correlate with people that just chmod 777 on server if something doesn't work and they don't understand why...
What's worse, is that a lot of people who seem to be asking for the same workflows actually have slightly (or significantly!) different conceptual models of what they want, so we end up in this weird place where we think we all want the same thing but actually don't.
If anything, git has clearly demonstrated that this is a complex space, and its perceived unusability stems from the fact that the operations it supports simply map onto basic graph operations.
Switching Git to Mercurial, or pretty much any other actual DVCS ain't going to make life of artist or someone tech-clueless any better, because while UI might be improved they still don't know what exactly they are doing or why
It’s also a UX nightmare. I work with tons of artists and engineers from the games and film industry.
Teaching git to an artist is painful. UIs work, till they invariably fall apart and then they’re confused again in the command line. Also most UIs can’t abstract the ideas to a good easy system.
Even a ton of very experienced engineers fall over when you touch rebasing etc…
Now people will say use Perforce. Well that has its own issues around branching/streaming and integration for code etc… plus you’re tied to their systems, and I’m not convinced their UX is great either, just better.
Plastic SCM seems to be the best so far but I haven’t really put it through the paces much.
Anyway I guess my point is: git is a fantastic technology marred with bad UX. It’s much like GIMP or Blender back in the day that had terrible UX as well, but have since improved greatly.
I’d love to see a rethink of the git UX at the UI level, that can guide even the most novice programmer through everything easily.
Edit: also I know invariably someone will say to make my own Ui instead of complaining. I’ve tried. I’ve done some novel things but it’s really hard to do from a top down level without also rethinking some of the base interaction model. That’s a battle I think needs a lot of effort across the stack first.
Ouch. Just use TortoiseSVN (+ svn)? I've had good success with it with business users.
Games, especially AAA games, have 10s or 100s of terabytes of source assets. Git was never designed to handle this. git-lfs is a hack to try to help here but it's bolting on a workaround for a system that was never designed for managing art assets.
It's also not designed to handle the fact that generally art assets are not mergable and so it doesn't handle coordination of editing assets (making sure 2 artists don't edit the same asset at the same time)
No amount of UX is going to fix that git is the wrong tool for managing art assets.
update: Googling for gamedev asset management this came up
https://www.perforce.com/products/helix-dam
I have no idea if it's good or bad but hopefully it shows some ideas for how git is the wrong tool for art asset management
Firstly, I’d already mentioned perforce.
But secondly , and this is my fault for not going into detail, I never said it was a game. There’s tons of software engineering categories with 3D art that are software heavy , so git wins out due to the ratio of engineers to artists.
Third, git with lfs configured from the get go isn’t that much worse than perforce with the exception of shallow and partial checkouts still being a pain. Otherwise perforce brings its own pains and UX hurdles. Streams and reviews for example are really rough to work with compared to git.
Lastly there’s just so much infrastructure around git. From hosting to CI/CD. Having multiple VCS is painful
git-lfs only solves storage. It doesn't solve the 50 other things that are special about art assets.
Lastly there’s just so much infrastructure around git.
All that infra has nothing to do with art assets though. Again, looking at art as nail because all you have is a hammer (git)
It’s easy to say “you should use XYZ” in a vacuum but there are often always tons of other reasons to pick a solution.
Thanks for your thoughts, but they assume I’m not well versed in the domain enough to make the correct decisions for my teams.
It’s also besides the original point that git has a very poor UX. Like yeah there may be things with better UX, but that doesn’t lessen the original criticism nor does it mean one should switch just because of it.
But DVCS is just a bit of complex system to get. "Good UI" in this case is just finding enough common use cases and making them easy that the average mortal won't have to think what commands they type actually do. Case in point:
> Edit: also I know invariably someone will say to make my own Ui instead of complaining. I’ve tried. I’ve done some novel things but it’s really hard to do from a top down level without also rethinking some of the base interaction model. That’s a battle I think needs a lot of effort across the stack first.
as did many other. DVCS is a distributed system(doh) and those generally make reasoning hard for ones not used to thinking that way.
Aside from that I think git would benefit greatly if it had --explain command that would try to explain in human terms what the command you're trying to run actually does
DVCS of any kind just requires certain bottom level of knowledge, if you don't have it you will just get yourself into trouble regardless on how good UI itself is.
Even with some improvements, git UI sucks to this day. Linus didn't care much about the chrome and had a special aversion against anything that smelled of SVN, including the names of the commands that actually made sense. And the worst thing is that Subversion wasn't even half bad - it was just bad for Linux kernel development. Most companies could easily use it today (and some still do).
Additionally, Mercurial with its consistent UI is/was (imnsho) far superior to Git. Git won mostly because GitHub was lightyears ahead of everything else (and in many ways still is), not because git is any way better than hg.
It's a very frustrating piece of software whose commands seem more reflective of it's design rather than what it was designed to do.
1- the model is not intuitive to beginners. There's a really tough learning curve.
2- the model is powerful but leads to a few specific workflow. If you don't have the same mental model and don't want to use those workflows, you will have the "misery" the author describes. Otherwise, you'll be perfectly fine.
3- no one has yet to do a great job of describing that model and workflow visually.
The author's "features from the future" feel to me like they just haven't gotten a good feel for the model. That's why they are miserable. That's partially because git's model is hard to learn, and partially because after all this time they still haven't taken an hour to deeply learn it.
Btw I would recommend GitExtensions for learning Git. It has the most intuitive interface I've found. For example it lets you browse the files at each commit which really shows how commits are snapshots, not diffs.
> For example it lets you browse the files at each commit which really shows how commits are snapshots, not diffs.
This is exactly the problem I mentioned. For one, each commit is a snapshot in the sense that it shows us a snapshot. Internally, it's a bunch of hashed and interlinked files. Git only collects them to show us a snapshot.
But you probably knew this already. The real confusing part comes when you have to amend a commit, merge branches, interactive rebases, etc. The changes between the commits are propagated as patches. Even the merge algorithm uses a 3-way diff. Rebases is all about diffing and patching behind the scene. Thinking that these are snapshot operations will make the operation much more hard to imagine and predict. You should know when to use snapshot model and when to use diff-patch model in Git. This part is also rarely mentioned in Git tutorials or tools (stgit on the other hand, exposes this diff-patch idea very well)
Yes. Again, merge conflicts are intuitive (there were two different edits to the same code; you have to resolve the conflict). But yet again Git makes things difficult - using words like "Ours" and "Theirs" (when they're often both "ours"). It even gets them backwards in some cases!
Rebases are also pretty intuitive. For once it's not too bad a name - you take all the changes in a branch and reapply them to a new base commit. Re-base.
> Internally, it's a bunch of hashed and interlinked files. Git only collects them to show us a snapshot.
That is the snapshot. It's deduplicated but it is still a snapshot. I'm not sure what your point is here.
> Thinking that these are snapshot operations will make the operation much more hard to imagine and predict.
It really doesn't. It just means you have to describe what things do properly. Rebase calculates the changes from one diff to another and tries to apply those changes again from a different starting point. Easy no?
I've spent a fair amount of time working directly with the object database, working with the latest Git features, filing bugs to upstream, working on my own source control extensions, working on successor version control systems (Jujutsu), attending and presenting at Git meetups... It's difficult to be more of a Git power user without being on the core developer team itself.
> If you don't have the same mental model and don't want to use those workflows
The workflows in question support the Linux mailing list patch workflow, which are described in `gitworkflows`, and are indeed what Git was originally created for.
Is it possible that maybe you haven't gotten a good feel for the model?
The author is apparently behind[1] a sucessful alternative UI to Git. It seems safe to assume that they are way beyond merely getting a feel for the Git model.
The Bad-UX denialism has really gone too far when authors like that are dismissed over the old You Just Have To Understand The Model talking point.
When I went through my university degree (which, admittedly, was over a decade ago), the skills and/or training for the day-to-day tools of software engineering - like git - were nearly never taught in a dedicated way in the same approach as concepts like data structures or algorithms. With degree in-hand the average graduate would probably be more comfortable reversing a linked list or estimating the O(n) of an algorithm than performing a git rebase. Yes, the latter is technology-specific rather than a generalized CS principle, but I would have to imagine that some capstone-type work would really spend time properly training a white-collar worker deeply on a standard few industry tools.
I'm not saying that the author is wrong, because git is indeed deviously inscrutable at times. However, after my twelfth or thirteenth failed merge or rebase, I really _dedicated_ some time to figure out what the hell git was doing from the ground up - which wasn't easy or quick - but I haven't felt truly mystified and incandescently angry at git since. It probably isn't fair to expect every Joe Software Engineer to spend that kind of time on each tool they're expected to use (I'm a masochist and enjoy doing it) but it bums me out to run into the occasional software engineer who never had the opportunity to engage in deep learning and/or practice about their closest tools like a nurse with an ultrasound machine or a court reporter with a stenotype. In a more perfect world a well-rounded software engineering education program would give people space for that, but we're left with "squeezing it in-between sprints" or "on weekends" because it's hard to imagine a company granting people ample time for professional development that doesn't transparently inflate OKRs.
Maybe my anecdote is out-of-date now and the situation is better, but I do still feel like most of us have had that "coworker had to blow away their local repo because git became too tangled" experience in recent memory. I also sort of assume that, in a paradoxical kind of way, code bootcamps may do this type of thing better, but I don't have that experience to draw from.
1) thinking university degrees are meant to prepare you for jobs. This is not why higher education institutions like universities came to be centuries ago. Universities are about sharing knowledge and researching. I would even debate 99% of jobs requiring a degree don't really, software development being one of those. Hell, one of the most important and famous chief surgeons in Italy, with various high impact papers. Was found to never have even started a medical degree.
2) Of all the degrees, I would safely say, SE and even CS are among those closer to day-to-day tools at work.
3) Extracting your experience and assuming it to be similar to those in other colleges, years, countries.
To me it feels straightforward now but I graduated the route of rcs->cvs->svn->git.
I think people get tripped up by the multiple layers there are between remote and local repositories. Remote->fetch->pull brings data to you. Save->add->commit->push sends it back. Then there's branches to add another layer of safety.
Git being difficult is a "hilarious" meme just like exiting Vim, or writing c++. Unfortunately people hear that and have given up trying to understand it before they've even tried.
Unless your company has a huge fixation with git history you really don't need to know much more than basics one can pick up with ease in what, few hours?
I never rebase in my life, I just merge the target branch and call it a day, most companies only track merge commits anyway so history is the same.