Where developers come to connect, share, build and be inspired.

287

Please, oh please, use git pull --rebase

70797 views

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.

Comments

  • Blank-mugshot
    rconklin

    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.

  • Blank-mugshot
    potherca

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

    git config branch.autosetuprebase always
    

    As explained by khasinski

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    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.

  • Clockworkelves_normal
    clockworkelves

    git is overcomplicated.

  • D931c33b2cff7edcefb78aecd7e6b45f_normal
    danaloni

    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'.

  • Me_normal
    randgalt

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

  • 294765_10150330995983461_21950553_n_sq
    simonbaird

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

  • Blank-mugshot
    carlzulauf

    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.

  • Blank-mugshot
    bdcribbs

    +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.

  • Blank-mugshot
    mattkeenan

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

  • Blank-mugshot
    dasil003

    @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.

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    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.

  • Img_0084_normal
    andrewtheis

    +1 For using git fetch and then deciding the appropriate action.

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    @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.

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

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

  • Blank-mugshot
    soggie2

    clockworkelves, life is overcomplicated too.

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    clockworkelves

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

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    @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.

  • Blank-mugshot
    losinggeneration

    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.

  • Blank-mugshot
    maandree

    From git pull --help:

    This is a potentially dangerous mode of operation. It rewrites history, which does not bode well when you published that history already. Do not use this option unless you have read git-rebase(1) carefully.

    I would rather have a safe and acturate history then a clean but incorrect history. I would never work with anyone that just uses rebase willy-nilly. And you do never actually have to use it, or at least I have never seen any such case.

    I would not even use it on a private personal repository.

  • 10534_128567884189_828694189_2287781_3877042_n
    khasinski

    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.

  • Userpic
    rwz

    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

  • Blank-mugshot
    maheshlal2910

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

  • Blank-mugshot
    sickill

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

  • Blank-mugshot
    ricokareem

    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')

  • Blank-mugshot
    kewah

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

  • Blank-mugshot
    montas

    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?

  • 1d2d212
    davidandrewsmit

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

  • Blank-mugshot
    fernandoperigolo

    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?

  • Blank-mugshot
    septagram

    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.

Add a comment