The tragedy is that git is so hard to learn. Start a github project (I know github is not git). Take a PR, have the PR have a conflict, now, try to explain to the new user how they can fix their PR via git to not conflict. You'll be stuck giving them a giant lesson, probably an hour to write the instructions, then several back and forths.
Mostly, either they already know git and fix it themselves OR I give up and merge it by hand myself since it's easier than becoming a git teacher for them.
Is this a Git problem? I recall entire workdays being wasted on SVN and CVS back in the day with multiple people trying to make sense of a merge.
In Git this is actually easier to do (and easier to do repeatedly, with git rerere and similar).
People tell me, "I'm so much more productive on the command line" and then it turns out all they know is pull/commit/push and using a local branch. Anything outside that brings terror: "I never use rebase. What if something goes wrong in the rebase? Now I've lost all my work and I have to pull a fresh copy of the repo from scratch."
Yes, I have heard exactly that.
One thing I love about SmartGit is how it unifies features that the Git command line presents as separate and unrelated concepts. The reflog? Click the Recyclable Commits checkbox and now all of your reflog commits show up as ordinary commits just like any other.
Stashes? Same thing. Turn on the checkbox to make a stash or all stashes visible and now they show up as ordinary commits, which is all they are under the hood.
Want a diff between two commits, whether they be normal commits or stash or reflog commits? Click one commit, ctrl+click the other, and you instantly see the differences between the two. No need to check out a reflog commit temporarily just to have a look at it.
Yet I have only had a 5-10% success rate in getting anyone to take a look at any Git GUI, much less using one. I would be really interested in understanding why so many developers are reluctant to doing anything other than the Git command line.
> I would be really interested in understanding why so many developers are reluctant to doing anything other than the Git command line.
In the spirit of curiosity, I downloaded the two packages. SmartGit shows me a document and outright threatens me to "deactivate". https://www.syntevo.com/blog/?p=4148 This is a euphemism for other people coming to my computer and deciding what I am able to do or not. I declined here. GitKraken shows a log-in screen before letting me use the software properly. It does not refer to the account I already have on my operating system and which is entirely under my control, but some other account which is under the control of other people. That account could be revoked at any time without my say in the matter and then I would not be able to use the software, on the face of it that's the purpose of the log-in screen. I declined here. As such, I did not even run the central part of the two software packages and cannot tell my opinion how well it would work, but I already learned what I needed to know.
I object to other people desiring to restrict how I use a software. This is fundamentally not compatible with my view on how I want to run my life, and that software/the people responsible for it have no business telling me. I will never consider these packages again. The software I have been using for years, namely qgit (a GUI) and the command-line tools, impose no such restriction.
There are many people who do enough git to know how it works well and be familiar enough with enough of the commands that they don't need a GUI and are likely faster on the command line. But for every one of those people there are at least 2 who would work faster, and more accurately with a good GUI.
I would add git bisect to the list. It's incredibly useful (if your codebase is sane).
In the best cases, it's totally automatic. You know that it worked at commit A and is broken by commit Z. So it checks out commit M and runs the tests. If they succeed, then it broke somewhere between M and Z. If they fail, then it broke somewhere between A and M. So it checks out either H or S, depending, and repeat.
It's not always that easy, especially when your tests and environment are complicated. There's often manual intervention, which is tedious. Still, log2 N steps is often manageable, especially if the computer is taking care of the tracking for you.
The other day I used it to write a good bug report. I first used it to find the earliest commit I could compile on my machine, then I used it to find the commit where a certain command would fail.
I still prefer to add/commit/branch/merge. I often copy-paste changes into a new branch, just because I don't enjoy recalling arcane commands from memory or googling them for the umpteenth time.
I suspect that git is a leaky abstraction that doesn't fit the corporate software development workflow. I think that git is a hammer and non-distributed development is the screw we're hitting with it.
Mind you, I'm not complaining, most utilities I've written for my internal users are worse! It's when something gets out and used by the masses that you wish you had had the time to put together a coherent user interface.
There's nothing inherently wrong with merging, but I personally don't like it because I find merge commits harder to understand than regular commits. Better to use things like rebasing and cherry-picking to move commits arbitrarily and then squash some commits into units of work that make sense.
Stash is crappy though, IMO, because it's not branch-specific. Instead of stash, I like to fork the branch I'm working on and create a "WIP" commit. That way I don't lose track of work I had in progress that only belongs in a certain branch.
Read "base" as "baseline"; that should help significantly for the simplest use of rebasing a series of commits without changing them.
This implies that they think in a wrong way and not have a wrong tool. A real tragedy is that git took over the world (in minds of lovers of shiny-new things and in saas) without most of the world realizing that they don’t even need it, because they wouldn’t even like to think in its way. The world wanted quick subversion and instead got this in-all-regards UX monster.
I never understood why people think this is a good pattern.
You rebase BEFORE you merge into the mainline branch.
In this model the main branch history is "real" in that it records the sequence of changes to the production code. It's "fake" in that it doesn't record the exact sequence of fumbling steps and backtracks you took to get there. But IME the latter is usually not very useful anyway.
A -> B
And you branch off B and start making changes, then the upstream continues on its own:
A -> B -> C -> D
Now you rebase your dev branch off D. Your changes get replayed on top of D and create new commits. Some of those commits might not be valid, because they take code that worked in the context of B and put it in the context of D. The history seems clean if all you do is look at the diffs, but if you bisect and try to use the repo in one of the rewritten commits, you may find it doesn’t even compile (even if that commit was fully functional before rebasing).
It tends not to be an issue when a developer is working on an isolated feature that only he or she cares about, that is reviewed in a timely matter, and gets directly committed to main.
Often this is not the case.
In my experience you can make an argument for a merge-based workflow up to around 6 people. By 12 it's painful and hard to track what's going on, doubly so when you have a dev branch and multiple sustaining branches or something more complicated.
By the time you get to 100 people or more committing to the same repo, it just becomes absolute chaos, and at least you can maintain a semblance of sanity in your official branches by forcing a rebase-based workflow on them.
git rebase master; Now, the snapshot pointed to by C4' is exactly the same as the one that was pointed to by C5 in the merge example. There is no difference in the end product of the integration, but rebasing makes for a cleaner history.
What does it even mean to have a rebase-based workflow? In svn-like terms, does it mean that you have to sync-merge before reintegrate-merging? If yes, why is rebase stated as if something completely non-existent before and reinvented? You do sync-merge before reintegrating in svn, otherwise you’ll apply ancient-based patches to the young trunk, which is obviously not what you want.
And if you do not use rebase, but use a merge-based workflow, does it mean that you apply ancient-based patches to the master? If yes, of course it will be a conflict hell, cause master could undergo few refactorings in the meantime.
It is so confusing when people talk in a different slang, and you can’t tell if they invented something new or just missed something so damn obvious in the old tech. Can you please comment on which of these thoughts are [in]correct?
A merge-based workflow maintains the work-in-progress history of commits running parallel to main before merging the two together. So your commit tree splits and reforms, with the number of branches at any one time equal to the number of people working on distinct features at one time.
It shows you how a feature evolved, which there is some benefit of, but at the cost of an explosion in branches that are now part of the permanent record of your codebase and the main branch you're working in. It rapidly turns into spaghetti with even just a few people working in the repo.
A rebase-based workflow will typically compress all the work in progress to a single commit, which then gets applied to the tip of the main branch. This maintains a linear flow of commits where each commit is a single PR.
Maintaining that linear flow of commits is increasingly important as the number of people committing to the repo rises and the branches rise with them.
Visually, a merge-based workflow might look like this:
4
|\
| \
/3 \
| 2\ |
\| |/
|//
|/
1
This would represent 3 features worked on by different people, all branched off the same source (1), and then merging back in.The same thing in a rebase-based workflow would look like this:
4
|
3
|
2
|
1
All of the work in progress is collapsed into a single commit when completing the PR to maintain the linear history. Of course while it was in progress, it resembled the merge-based workflow above. The difference is that instead of merging at the end, they rebased and squashed the commits.Again, the end result in terms of the code is the same. The difference is what you see when you're navigating the history of the repo.
merge-based ... rapidly turns into spaghetti with even just a few people working in the repo
Isn’t it just a detail of how graph/report tools work? Can’t they track these merge points and “rebase in their ram”? I don’t get how a graphical representation of merge points may change the workflow.
One more thing that is unclear is why some people think that rebase is somehow superior in terms if conflict and reintegration. Like they “had issues with svn and now that rebase is a thing, issues gone”. Maybe they didn’t understand that you have to sync-merge your branches (effectively rebasing) periodically to not diverge from trunk (or parent branch) too much?
Added: I know rebase is not congruent with what I’m asking, but my questions are more about how git folks think, not about how git works. Cause I often see its comparison to other VCSs and claims that are vaguely or simply untrue about git competitors. As if before git there was some stoneage.
DVCS have a DAG of commits, which can get arbitrarily complicated and difficult to reason about.
Rebase-based workflow results in a linear history of commits, which is easy to reason about.
Merge-based workflow results in an arbitrarily complicated DAG of commits which is difficult to reason about.
That's all there is to it.
The repo rapidly turns into spaghetti with a merge-based workflow because all the work in progress is now part of the historical record for any particular commit to main. You're not looking at a single commit, you're looking at a chain of commits and a merge node. Now imagine there are 20 people committing to the same repo. Your branch factor is exploding! Imagine the picture of my merge-based workflow, but multiplied 7. It rapidly becomes very difficult to navigate.
The DAG is important as a historical record because you have to go back to it on a very regular basis.
It doesn't change the workflow from a "do your work and commit to the repo, periodically sync with main" perspective. It changes the workflow from a pull request perspective.
I've found rebase is (slightly) inferior for conflict resolution and reintegration--mainly because unless you squash your commits down to a single commit, you may need to resolve the same conflict as many times as you have commits after the conflict in the worst case, which is irritating. Merge is just one and done. But that's a minor thing.
Having used SVN (briefly) and Mercurial (a lot) and Git (a lot), SVN pushes you into dealing with a single linear history of commits, with cross-branch merges being extremely painful and error-prone if anyone else has worked in the same area. DVCS like Mercurial and Git allow you to do whatever you like for the history, and cross-branch merges are generally easy and pain-free. I can't say anything about the underlying implementations and why it is that way, but that is my lived experience.
Most of the time with Mercurial and Git I can let the merge tool resolve differences if there are conflicts with the odd line needing manual intervention. Most of the time there aren't conflicts.
And having used SVN a bit...yeah, it's the stone age in comparison. Sometimes you have to make that tradeoff because you can't store everything locally, but I haven't enjoyed the times I've had to use SVN after having used Mercurial and Git.
And Git's user interface sucks.
I need a Mercurial skin on top of Git so the commands make sense.
And I don't mean memorising commands and their arguments, but rather understanding Git from first principles.
(I wrote this visual tutorial for that purpose, takes about fifteen minutes to go through : https://agripongit.vincenttunru.com/)
Think of your git history as a product and art form in itself. If you don’t enjoy writing your commit history, readers will not enjoy reading it.
On a tactical level, I highly recommend buying Sublime Merge 2.
Maybe distributed source control really is this complicated and treating git as a deep skill is justified, but having also used Darcs and Mercurial I have a hard time believing that git's usability issues are inherent complexity and are in fact an artifact of git itself.
Personally, I've settled on
* Getting pretty familiar with the git command line
* Using a decent GUI diff and three-way merge tool (I use Kaleidoscope)
* Using GitUp, an open source Mac git client, on occasions where I want to get kind of arcane: committing individual lines of files in separate commits, re-ordering commits (on an unmerged feature branch because I'm not a complete monster), etc.
I suspect having already discovered GitUp is a good chunk of why I didn't get into Sublime Merge; it can do a lot of advanced stuff in ways I personally find easier to grok.
I do agree you should learn rebase, reset, cherrypick and stash, but I don't agree that you need to learn on the CLI. I mean, use the CLI if you prefer that, but the git GUIs are perfectly adequate for performing any of these operations.
I used to use git CLI heavily, but in the past few years I have simply not needed to, to the point that aside from a small handful of the most common operations I don't even remember a lot of it anymore. Partly this is due to maturity of the GUIs, and partly because old practices like SSHing to a dev server to edit+commit something there are just totally obsolete and unnecessary these days.
Even for a simple commit, there's a massive convenience of seeing the timeline and being able to interactively stage and look at diffs that is just miles ahead of CLI, and lets me break down commits into better units of work and write better messages.
There's a stupid gatekeeping thing some developers still do about git CLI, I don't get it. It's as valid as dictating what text editors, color schemes, input devices, or OSes "real developers" use. Judge people on their output, not their tools.
I guess that's part of what I was getting at though. Where are you doing your development that isn't your workstation?
I work on a whole bunch of different things -- from personal stuff running on my laptop or VMs in my house to cloud services deployed across dozens of AWS services -- and things have just got to a point where I have no need to do a commit anywhere but my workstation. (Well, technically, I have two: one personal, one work).
I definitely used to do it years ago, but now I don't remember the last time I had to use git on a remote system.
My goal is to have my code in the repo. So if git starts being a pain, it’s much easier to store my edits locally, pull a fresh copy of the repo, copy over my edits again and commit + push.
If you have a good cook, let him/her cook dishes and let someone else care about sharpening the knives and cleaning the dishes.
If you have a brilliant programmer, let him/her write good code. Don’t bother them with understanding binary trees and hashes of snapshots of diffs of local repo’s of pointers of objects in a blob graph lalalalala.
This is because Git is too hard to use.
How do I know that Git is too hard to use? Because there are literally thousands of blog post tutorials explaining how easy Git is to learn. Things that are easy do not need thousands of different guides telling you how easy it is.
Git is hard to LEARN. It is objectively very easy to USE for those who have learned it, so much so that the population of "I used to use git until I found ..." evangelists is effectively zero. Tools like mercurial exist in the marketplace of ideas mostly by peeling off users who haven't yet started using git productively by promising 80% of the features for 10% of the effort.
In fact, I don't know that there has been a new tool since vim or emacs that so well illustrated this dichotomy between ease of learning and ease of use.
But to be honest: it really is needlessly hard to learn. The content of the linked article is that git is built on an extremely simple foundation of data structures and operations that anyone can understand. But the takeaway from the article is that no one does understand it, because that layer is hidden behind a facade of tools that completely obscure it. Where are the "blobs" in git reset? What is the "index"? Is it a "tree" (it's not, IIRC)? I definitely agree with people who complain about the porcelain layer's design. But I still use git every day and love it.
When you're working on a codebase with multiple people, there are going to be changes and the changes have to be consolidated and the conflicts have to be resolved. I believe, with a reasonable amount of time and effort, developers can learn that API and vocabulary and I have yet to encounter anything comparable in terms of ease of use and "grok-ability" - especially with modern GUI tools.
git is one of the most ubiquitous and unavoidable technologies in software development and it's 100% worth the time and effort to understand and be good at it.
I think a large amount of content is more a factor of Git's ubiquity than its difficulty.
Nobody writes tutorials on how easy Lyft or Uber apps are to use. Easy interfaces don't need lots and lots of tutorials. That's exclusively the result of poorly designed interfaces AND complicated systems.
That being said, I googled "How to use Lyft" and there's a ton of results.
Google: What is a system
Good luck.
> How do I know that Git is too hard to use? Because there are literally thousands of blog post tutorials explaining how easy Git is to learn. Things that are easy do not need thousands of different guides telling you how easy it is.
I'm not sure that's convincing. I think that a lot of guides about how easy it is indicate that it's slightly difficult to learn. That results in a lot of people struggling for a little bit, overcoming the struggle, and feeling a sense of accomplishment and enlightenment, which they then want to share.
(There's also a difference between how hard something is to use and how hard it is to learn. I'd argue that there's often a trade-off to be made, where some sacrifice on difficulty learning results in a reward in ease of use—in the sense that, for example, vim is far easier to use than any other editor for a seasoned vimmer.)
I hate all of them but learned to use them because what's the alternative?
Not from my experience as a newbie with SVN at the start of uni and in the beginning at $job.
In both cases, it was temperamental, prone to network issues (this was in both student accom. -> uni server, and LAN at $job) and did not like users working on the same files.
Git took some learning, and it took reading Git Magic <http://www-cs-students.stanford.edu/~blynn/gitmagic/> to go from <https://xkcd.com/1597/> to the friend mentioned in the alt text.
SVN still feels like I'm pulling teeth all these years later.
I couldn't agree more. It's not only enabling more sensible interactions with the people that collaborate on repositories with you, it's also a comfort that allows to experiment and take benefit of the tool without fear of getting stuck.
I would add checking the reflog and how to use it to complete the list, even if it's clearly less important.
A source that I recommend wholeheartedly for those that want to go further down the git rabbit hole: https://learngitbranching.js.org/
Maybe rebase is a tool to help poor software development practices? (and your colleagues letting branches go stale is one of those)
Says someone who's "never looked at our git graph".
What are branch and merge? /j
Because a lot of people have been burned and way too many hours been lost due to a rebase gone wrong. Cherry-pick and stash are trivial operations, reset (outside of "undo a git add") and especially rebase are not.
The learning curve for both is steep, the potential for failure extremely high, so I understand why organizations go as far as entirely banning rebase.
It's so bad that even seasoned developers that haven't delve deeply into git have no idea that this sort of rebase is practically harmless. Instead they parrot "Rebase is Evil" without thinking twice.
A lot of people are scared of rebase and cherrypick and shut down or get defensive when you mention them or try to encourage their use.
The result is, because developers only have a hammer, they brute force merge everything which results in grotesque conflict resolutions and commit histories and makes it hard to untangle problems.
At a previous job, another developer was kind enough to walk through rebasing on the command line with vim. I was receptive and in about 10 minutes, I realized there was a significant set of standard features and day to day Git use I was previously just oblivious to.
These days, the UI for rebasing and cherry picking in Gitkraken is state of the art and effortless and I use them every day without hesitation and without the fear that comes from not understanding or knowing what I'm doing. Still, I constantly struggle with coworkers merging feature branches from 100 commits ago in to new feature branches and brute force resolving conflicts across half a dozen files in one commit without any context.
I see it all because I have visibility in to the history and branch relationships but I still get shrugs and eye rolls when I bring it up. I don't necessarily want to dictate nitpicky git usage but I have a hard time accepting when people just to refuse how rebasing and cherrypicking work when they're both core basic features of a tool we all use every day. Proper Git use is one of those hills I'll die on, though so I don't intend to shut up about it any time soon :)
Edit: My practical advice: If you use git every day and you don't know how to rebase, reset, cherrypick, and stash from the command line, make it a goal. Then, once you're comfortable, learn how to do it in a visual tool like Gitkraken and make an effort to incorporate them in to your daily workflow. My guess is things will become a lot less tedious and confusing when things get messy.