I don’t recommend git pull to anyone. The magical ways that .git/config sets up tracked vs untracked branches are too opaque for me.
It’s always been much easier to understand (and explain) what’s going on when you separate fetch from rebase/merge*, and I feel like all these “just re clone and start again” memes are all because people’s branch tracking broke and they wanted magical “git push # no further args” to work properly again.
Once you know how to “git push remote myref:theirref” you become much less dependent on magic. Knowing about / having to know about how it works internally is the fun / tedium of git.
*Just kidding about doing git merge, btw. Linear history for life!
Fetch means “safely fetch new data from one of your remotes without affecting any of your local work”.
Pull means “do what fetch does, but with the spicy bonus risk that your precious work will be modified in an unexpected way depending on when and how you checked out the branch you’re on, what version of git you are using, and what config options you have set.”
Most confusion I've ever seen from beginners comes from them trying to pull, ending up in a conflict and not realizing, not resolving it but not aborting either and just continuing their work and then getting confused when trying to do anything else.
That's true. I think the worst thing about git CLI is it hides the state and forces you to issue another command to query the state, but you could easily forget. A lot of people add the thing to the PS1 to show some state, but it's not default.
However, I'm still not sure git will actually fuck things up with a pull. I think that's the users later when they go nuclear and delete the repo.
> Pull means “do what fetch does, but with the spicy bonus risk that your precious work will be modified in an unexpected way depending on when and how you checked out the branch you’re on, what version of git you are using, and what config options you have set.”
That's going to happen anyway when you need to rebase/merge. May as well type one command (pull), deal with the conflicts and continue, rather than type command, type another command, deal with the conflicts and continue.
Unless you have some other strategy that does not include rebasing or merging upstream changes, there's no advantage to not pulling. And, TBH, if you workflow is "this branch is worked on while specifically ignoring other changes by other people", then you have bigger problems than version control.
> Unless you have some other strategy that does not include rebasing or merging upstream changes, there's no advantage to not pulling.
Of course there is: after fetching you can see if there are differences between upstream and local, you can inspect those difference, and you can decide how to reconcile the two.
“Pull” is a big hammer which unconditionally performs an integration operation, and the default integration is one you almost never want too.
There‘a no advantage to pulling IME, in the best car scenario it’s just an alias for “git fetch && git merge”, if that’s what you want you can just do that and create your own alias.
> Of course there is: after fetching you can see if there are differences between upstream and local, you can inspect those difference, and you can decide how to reconcile the two.
[FWIW, it seems you know more about this than I do, so don't think that I am purposefully trying to be annoying. I'm not, I hope :-)]
I agree that you can see the differences, but I'm asking how helpful is this.
For me, anyway (not an advanced git user) seeing the differences between master and my feature branch before doing the rebase makes no difference - I'm still going to do the rebase no matter what I see in the feature branch.
It is going to be rare for me to be able to see, of the 10 merges to master, if an of them are going to break the code in a way that I cannot continue (in which case I won't rebase).
The longer I put off rebasing, the harder it is going to be to do it, so I am highly motivated to rebase on whatever master has, even if it just got broken, because it will be more painful to rebase later.
One big benefit to fetch+rebase over pull is that you can create a backup branch before you rebase so that if you mess up the rebase too much, you can undo easily.
Another situation I've run into is that sometimes I've made a small change that's stacked on top of a lot of other branches. And if those other branches get squashed and merged, regular rebasing can be really annoying - it is often easier to cherry-pick (I use rebase --onto, but same idea) your changes onto main/master instead.
> If you mess up a rebase you can always rebase -—abort (/ use the reflog) to restore the pre-rebase state.
That is true. But a few times, I've finished rebasing and regretted how I handled conflicts. And once the rebase is complete, you can't abort any more.
And I haven't put in the time to learn how to use reflog. Maybe this is my sign to do so.
As in `git fetch ...; git reset --hard ...;`? I guess that is what people are trying to achieve a lot of the time... For some reason people are more scared of `reset` than `pull`, though.
>Fetch updates your local repository (which is behind the scenes, separate from your literal local files).
Therein lies the chief problem with git: it's a leaky abstraction. Nobody actually should give a flying shit about commit hashes and ^HEAD or whatever it's called.
All the newbie tutorials you find waste so much time on that, but what people really care about when they start using git is "what the fuck happened to my files and how do I get them back the way they were".
Git docs and tutorials are breathtakingly bad at showing this.
git pull with fast-forward (--ff-only) is the only sane way to use git pull (if one must use git pull).
The most powerful one most people don’t use is reset. Soft and hard resets are my bread and butter. I don’t even bother with interactive rebases for squashing. I do a soft reset against origin/<branch> and create a new commit.
Yes I agree. Have you ever seen the "command line instructions" GitHub prints at the bottom of pull requests to checkout the PR code?! I don't think you'd approve of them. I'm pretty expert at git having used it every day for the last 15 years or whatever and I have no idea how to do anything after following GitHub's instructions!
To do it sanely you need to add the contributors remote, and fetch, and checkout, as usual. Would be happy to be educated here if I'm missing something.
It’s always been much easier to understand (and explain) what’s going on when you separate fetch from rebase/merge*, and I feel like all these “just re clone and start again” memes are all because people’s branch tracking broke and they wanted magical “git push # no further args” to work properly again.
Once you know how to “git push remote myref:theirref” you become much less dependent on magic. Knowing about / having to know about how it works internally is the fun / tedium of git.
*Just kidding about doing git merge, btw. Linear history for life!