Last Updated: March 08, 2024
·
561.4K
· khasinski

Please, oh please, use git pull --rebase

When working on a project you usually synchronize your code by pulling it several times a day. What you might not know is that by typing

git pull

you actually issuing git fetch + git merge commands, which will result with an extra commit and ugly merge bubbles in your commit log (check out gitk to see them).

It's much better to use

git pull --rebase

to keep the repository clean, your commits always on top of the tree until you push them to a remote server. The command will apply all your yet-to-be-pushed commits on top of the remote tree commits allowing your commits to be straight in a row and without branches (easier git bisects, yay!).

Few notes though. If you want to merge a feature branch it might be wiser to actually merge your commits thus having a single point of integration of two distinct branches.

Also the conflict resolving will be now per commit basis, not everything-at-once, so you will have to use

git rebase --continue

to get to the next batch of conflicts (if you have any).

NOTE: Because of many discussions about this note. I DO NOT encourage rebasing remote (public or shared) branches. Rebasing local history is OK (it's more than OK, it's sometimes necessary to maintain a clean history), but changing other people commits history is considered a bad practice.

38 Responses
Add your response

oh, i didn"t knew you could do that. i was doing the same thing in a slightly more verbose way:

git fetch
git rebase origin/my-branch

great advise, thanks

over 1 year ago ·

You can get even shorter version as I described here:
http://coderwall.com/p/yf5-0w

over 1 year ago ·

I tried explaining this to a colleague of mine about two years ago and he simply couldn't understand.

over 1 year ago ·

It's a lot easier to just set rebase as the default using

git config branch.autosetuprebase always

As explained by khasinski

over 1 year ago ·

I never use 'git pull'. The reason is that I want to fetch - look at what other people changed, and only then decide whether I'd like to rebase to those changes now, while I'm doing my stuff locally.

So my advice - unless you know exactly what you are getting from the remote branch, don't use 'git pull'.

over 1 year ago ·

Rebase by default when doing git pull: https://coderwall.com/p/tnoiug

over 1 year ago ·

I use git pull --ff-only (aliased as git p) so if the pull is anything other than a fast forward I have to stop and think about what I want to do about it. Rebasing when I think I'm going to fast forward is not a behavior I want. If I decide a rebase is really what I want I have a git prb alias too.

over 1 year ago ·

No - I want to see the full history. No rebase please.

over 1 year ago ·

I prefer to git fetch then git rebase (or merge if appropriate) manually.

over 1 year ago ·

+1 for not using git pull. Use git fetch, and then decide on the appropriate action.

In addition, I don't commit or merge onto master (or any shared tracking branch) until I'm ready to push, so I very rarely have a fetch that isn't a fast forward anyway.

I do tend to rebase my development branches.

over 1 year ago ·

git is overcomplicated.

over 1 year ago ·

clockworkelves, life is overcomplicated too.

over 1 year ago ·

Please don't use rebase if other people rely on / pull from your codebase; use merge instead.

over 1 year ago ·

case 1: I want to push my code changes only (no merges), and I my local branch is out of date

  • git pull –r (or pull - -rebase)

case 2: I need to push a merge I just did, and I my local branch is out of date

  • git pull (If you have 'git pull' aliased to 'git pull -r', then 'git pull --no-rebase')
over 1 year ago ·

clockworkelves

Check man git, you'll see it's 'the stupid content tracker' ;)

over 1 year ago ·

And if you are lazy to do git fetch & git rebase you might use https://github.com/aanand/git-up

over 1 year ago ·

@randgalt - You want to see every burp and hiccup along the development timeline? Why not take that viewpoint to the logical endpoint and auto-commit after every character typed?

Oh would that be insane? Because it's useless noise in the history? What you actually care about was the developers intent? Now you're starting to see the light. Once you grok git you realize the value of crafting your local commits to provide an immaculate and bisectable project history to the outside world.

over 1 year ago ·

why would you git pull before you want to push?

You pull something, work on it, and when you are done, then you pull, check if everything is working and push.

Why would i resolve problems with remote changes multiple times a day if i'm not done with what i'm working on?

over 1 year ago ·

montas

Because sometimes you can work on something for a couple days and you don't want to diverge so much from the original branch. Keeping codebase synchronised is often cheaper than solving lots of conflicts when you want to push.

over 1 year ago ·

The problem with rebase is that it corrupts the true history of the commits. This doesn't show up on a smaller repo, but if you have a busy repo, with lots of contributers, untangling a mess becomes much harder if you no longer have the true parentage of a given commit.

Git rebase destroys the context of the commit, leaving basically a diff apply instead of the much more contextually rich merge commit. Yes, your repo looks messier, but it more accurately reflects the lifecycle of the code, and what the developer intended at each commit. If you really want a straight-line for your repos, why aren't you using something like SVN? Is the distributed nature of git really the big selling factor?

I've run teams that have used git how you are describing, always making people use rebase (in this case it was because we were syncing to SVN). Reconstructing what a developer did 4 months ago is much simpler with a merge vs a rebase. You can go to the merge just before the developer's first commit and see what the repo actually looked like when they started work. You can never do that with a rebase. The context in which the developer was working has been lost. Also, with multi-commit branches, you can see what the repo looked like after each commit. With a rebase, those intermittent commits are almost useless, as the repo doesn't look like it did when they made that commit.

To sum up, don't subvert git just because you want to see a straight line in your commit graph. It's not worth it, and it is ultimately a lie.
</rant>

over 1 year ago ·

rconklin

It's a popular misconception that git rebase destroys history. It rearranges it into something else. Context isn't as important as you might think and rebase is a tool for LOCAL rewriting of history, not REMOTE rearrangements. That's the basic difference between SVN-likes and a distributed VCS.

Remember - you're only rebaseing your own code, often on a feature branch. It's your own history (until you push it somewhere).

If you don't understand that you're going to have a bad time with any DVCS and have ugly, hairy history that is basically unreadable to anyone bisecting, looking for bugs.

It's your option (feature branches with merges) that's available to SVN users. Making history useful is something available only to DVCS.

Don't limit your git to a subversion clone with better merging, produce useful commit history.

over 1 year ago ·

@losinggeneration
It's about git pull --rebase, not any other kind rebasing. It's pretty clear it's local. ;) But I'll add a notice to the original note.

over 1 year ago ·

@losinggeneration

git pull --rebase locally and then pushing to remote branches won't change anyone's history except yours. :) It's OK to do it. In fact - you should do it. Are you talking about people pulling using public (remote) branch (resolving pull requests)? Pull requests should demand that the said code apply in a clean manner (demand rebasing PR code against current HEAD) and use merge -no-ff option to indicate resolved request.

over 1 year ago ·

Well I'm embarrassed. I had to facepalm myself when I realized the issue I was seeing was from people doing a rebase of master from a branch and then pushing (which is where issues really crop up from the history being changed.) So you're quite right. Can I just blame it being too early in the morning ;) I'm going to retract (delete) my above comments.

over 1 year ago ·

I'm a huge advocate for using git fetch and then deciding upon relevant action.

over 1 year ago ·

Pull with rebase wont push changed history unless you have multiple remote repositories in which case you should know git better. You never have to use rebase, you can always do a revert commit. But it makes your repositories unreadable and sharing code so much more difficult.

over 1 year ago ·

If you are working in a branch with a friend, a think git pull --rebase is the must.
But when finish the fix/release, i recommend use fetch and merge.

git pull --rebase is really a #protip, but exist a specific times to use it.

Anyone agree?

over 1 year ago ·

Personally, I follow a simple rule to both keep my history clean and retain commit parentage. When I'm merging a new branch for the first time, I rebase and do a fast-forward merge. If it happens so that the issue is still not done, I continue working on that branch and all subsequent merges are --no-ff without rebasing. So, all branches maintain continuity through the commit log (basically, it remains a single chain of commits) without crowding it with petty one-commit "made the copyright font size 0.1em smaller" branches, that take twice as much space in the best case (in the worst case they are based on a commit a few weeks ago and take quite some scrolling to figure out what they are).

Aside from that, I pretty much adhere to Git flow, having master and develop branches, as well as the occasional ones for hotfixes and releases.

over 1 year ago ·

I agree with @rconklin, rebase is a useless lie; on top of which it can introduce dumb merge conflicts in some cases. If you want to look at a pretty straight line of commits, just do git log --no-merges

over 1 year ago ·

I don't normally use git pull myself rebase or otherwise. What I do often on my feature branch is git rebase origin/master (or whatever the shared development branch is) to make sure I am working on the correct level of code. Last one in is the one responsible for making sure code works with existing.

It would be helpful to note that the branches are generally short lived and not super all encompassing in code changes usually.

over 1 year ago ·

If you have Ruby:

$ gem install git-up
~/myrepo $ git up

It rebases by default and pulls all your upstream branches instead of just your current one. Also, colours, yaaay!

https://github.com/aanand/git-up

over 1 year ago ·

Surely the right thing is to have the commit log store all information (not hiding it by rebasing), but have better tools for simplifying the log when you view it?

over 1 year ago ·

Having used both Git and Svn, I see the beauty of maintaining a linear history and yet appreciate the beauty of branching and merging. I understand that there is no absolute right or wrong with either approaches but I feel that there is a right time to rebase and a right time to merge.

Eg. if a team of two or more works on a single feature branch, I would get them to rebase their commits on top of the latest remote feature commit. This is to maintain a linear commit history on the feature, The benefits of doing this in my opinion is that it becomes easier to code review their changes for that particular feature and see what each dev has done.

To keep things simple and avoid fixing a massive pile of conflicts, we would merge from develop to the feature branch every now and then to ensure that changes from other teams are integrated with the feature(maybe daily). When the feature is complete, it is merged back with develop.

What are everyone's thoughts to this hybrid approach?

over 1 year ago ·

Few notes though. If you want to merge a feature branch it might be wiser to actually merge your commits thus having a single point of integration of two distinct branches.
Also the conflict resolving will be now per commit basis, not everything-at-once, so you will have to use git rebase --continue to get to the next batch of conflicts (if you have any).

I’m not sure if I understand what you mean .. can you explain that a little bit

over 1 year ago ·

Best practices typically spread quickly and early when they make sense and particularly when they are trivial to achieve. That is not the case with rebase. Why? It's disastrous generally speaking. Krzysztof, you are wrong about rebase not changing history; that's actually a fact not a misconception. Of course, if you want to assert rearranging history isn't changing it, that's your prerogative.

You cannot talk about rebase without making it very clear that you must NEVER rebase a shared branch. That means a branch that two or more developers are changing. Even in the case where you are the ONLY developer, your attempt to push your sequential rebase changes will be rejected, and you must use the "force" push option -f. You can pencil out what a disaster it is to rebase shared branches. Total havoc.

Now, having said that, you should continuously rebase your defect or feature that only you are working on. In other words, always create a personal branch, then rebase against the shared branch. ALWAYS rebase origin/shared-branch versus just shared-branch, so you rebase against the shared branch and can ignore your local version if you have one. You probably need to "share it" for a pull request; no problem, but you'll need force push to update it, and again, nobody else should push to that.

So, yes, rebasing creates a nice linear history by keeping your changes together and pasting them on top of incoming changes. Just follow the simple rule of never into a shared branch, which is typically how good developers work anyway. If create a pull request, and have to fix something up, make sure to force push (do not panic) when your changes are rejected because the repositories have "diverged"

over 1 year ago ·

great, khasinski, thanks)

over 1 year ago ·

I do not really agree with that last note paragraph.

For work branches, it is extremely useful to rebase them onto the current master instead of constantly merging master into them and generating tons of merge commits. And if everyone pulls with --rebase, it will not cause them any trouble. (And if not, it has the beneficial side effect of teaching people to use --rebase next time. 😜)

over 1 year ago ·

I haven't seen it mentioned yet, would be nice addition to the post: it can be automated!

git config --global pull.rebase true

et voila, all git pull are implicitly git pull -r.

8 months ago ·