9 ms·
Please use git pull --rebase
- pcl 13y agoSo it definitely keeps history nice and pretty, and I use it for simple commits all the time. However, sometimes I do 'git pull --no-ff' explicitly, because I want a more-complex multi-commit sequence of operations to stand out as a unit of work. I really wish git had a primary concept of such a thing. I understand that hg might, but haven't had an opportunity to get that far into an hg project yet.
- kibibu 13y agoI've been burned a number of times by hg rebase, losing work in each case. Given that our team only has 3 committers, I'd rather deal with the messy tree than lost work.
- ngoldbaum 13y agoThe rebase extension for hg is still a bit experimental, at least as I understand it. It will be much better once changeset evolution [1] is turned on by default in a stable release. [1] http://mercurial.selenic.com/wiki/ChangesetEvolution http://mercurial.selenic.com/wiki/ChangesetEvolution
- kibibu 13y agoThat looks nice; in particular `hg fold` solves the "messy local, clean remote" problem nicely.
- X-Istence 13y agoWhat do you mean a primary concept?
- pcl 13y agoThe use case that comes to mind first is 'git bisect'. I love that feature, but I also love to leave a messy trail of commits in my history. In other words, I expect that there will be commits in my history where a full test run might not work, or maybe even things might not compile. Of course, that sort of thing royally messes with 'git bisect'. If git had a primary concept of "here's a synchronization point", then it'd be much easier to build tools like 'git bisect' (and even 'git log' etc.) around those sorts of paradigms. That'd offer the best of both worlds -- rich, detailed history showing how something got done, but also points at which it was believed that all was good in the world. A push is (should be?) a natural synchronization point, for example.
- to3m 13y agoSome form of nested commit would be useful for this I suppose - it would be arranged with something like an interactive rebase, that would squash a sequence of commits into one (for the purposes of log and bisect and the like), while leaving the original ones still accessible. This would give you your neat history for most purposes without losing the original commit comments and original sets of individual changes. This is of course a bit like how branches are merged together ordinarily, at least if you don't go around deleting them the moment you're done with them. And sure enough it looks like you can sort of persuade git bisect to treat ordinary branch merges like this: http://stackoverflow.com/questions/5638211/how-do-you-get-git-bisect-to-ignore-merged-branches http://stackoverflow.com/questions/5638211/how-do-you-get-gi...
- eru 13y agoProbably the same thing as `first class' in `first class functions'. See https://en.wikipedia.org/wiki/First-class_function https://en.wikipedia.org/wiki/First-class_function
- aiiane 13y agoPerhaps better stated as "please, oh please, actually pay attention to history" - there are times when rebase is appropriate and times when merge is better.
- khasinski 13y agoYes, but I used the title for people to actually start using rebase. Caring about history beyond avoiding useless merges and broken commits is another step I'd like at least my co-workers to take ;)
- wonnage 13y agoWhile this makes sense when dealing with a central repo (which I agree is the vast majority of use cases), it's inaccurate. You're rewriting history so that it looks like your work happened on top of $REMOTE's work, when in reality it was the other way around. This becomes a problem if you're working with multiple remotes, and which remote you pulled from, and when you did it becomes an actual concern. Concrete example: if I'm the maintainer of wonnage/foo and bar submits a pull request from bar/foo, using git pull bar --rebase doesn't make a whole lot of sense.
- kelnos 13y agoOf course, that's absolutely correct. But that's the minority use case, at least in my experience. Git's default is set up that way because of how the Linux kernel maintainers work, which isn't how most organizations who use git work. Even though git is distributed, most orgs have a central repo that they use as the source of truth. When contributors pull from this central repo, IMO they should be rebasing, not merging. When the maintainer pulls from other people, yes, he should of course be merging. The merge commit that a contributor implicitly creates when they resync with upstream (without rebasing) is ugly and confusing. It provides no useful information and only serves to clutter the project's history, not make it clearer.
- jedbrown 13y agoA topic branch workflow is tremendously useful even without separate people in the "developer" and "integrator" roles. For example, we have about 20 people regularly developing code and about five of us "integrate", first to 'next', then to 'master' when a feature has stabilized. We don't explicitly pass an integrator token so there is a possible race to the integration branch, but since we only merge there, it's actually pretty rare in practice. If you lose the race, the polite thing to do is discard your old merge, fast-forward, and repeat the merge. This preserves first-parent. http://git-blame.blogspot.com/2012/03/fun-with-first-parent.html http://git-blame.blogspot.com/2012/03/fun-with-first-parent....
- erso 13y agoYour example is incorrect. If you're the maintainer of wonnage/foo and bar submits a pull request from bar/foo, bar/foo should have been rebased on top of wonnage/foo, not the other way around. (And if you are in a situation where rebasing on top of bar/foo would actually do anything, that means you have local commits that haven't been pushed to origin, in which case accepting the pull request is dangerous.)
- deleted 13y ago[deleted]
- reyan 13y agoOr use git-smart (https://github.com/geelen/git-smart https://github.com/geelen/git-smart). It adds three commands to git. One of them 'smart-pull' which "will detect the best way to grab the changes from the server and update your local branch, using a git rebase -p if there's no easier way. It'll also stash/pop local changes if need be."
- ultimoo 13y agoWhile such wrappers around git always pique my interest and and are created with noble intentions, I am yet to find a team of developers who use such tooling around git. There are dozens of wrappers and workflows around git that have been created in the last 3-5 years and frankly it only complicates the shared vocabulary that developers use when communicating with one another. Also, distribution of such wrappers is usually in the form of rubygems which, although a low-barrier distribution mode, is complicated to use with rvm or rbenv of existing projects .
- mbillie1 13y agoThe only git-related tool I like is tig - it's an interactive git log, where you can scroll through commits and view diffs (and lots of other things) without having to copy+paste or use awk or whatnot. This tool (git-smart) seems like... I don't know. For me, I'd rather have my team suffer the learning pains of git than rely on a tool that, in some cases, will fail and leave them even more helpless than they were when they struggled to learn git. I do recommend checking out tig though; that's the one that I have kept. It's also not a gem, it is available through yum or apt (and probably pacman, brew, etc).
- ultimoo 13y agoYes, I am actually guilty of using `tig` for a long time too. :-)
- Smudge 13y agoAs a quick illustration, this is what can happen to the commit tree when just one of your team members doesn't rebase by default: http://pastebin.com/cnPbg0vm http://pastebin.com/cnPbg0vm
- Randgalt 13y agoNo rebase please. Let's keep the history accurate.
- mpyne 13y agoThat's just it. It does keep the history accurate, if you're literally just trying to grab updates from upstream. Unless you're actually working on, or merging, a separate branch then normally rebase is what you want.
- DoubleCluster 13y agoIt does NOT keep history accurate. You have absolutely no guarantee that all rebased commits work as intended or can even be built. The only thing that can be rebased safely is a single commit, for the rest you should learn to live with a messy history. It doesn't really matter anyway as long as you have procedures to prevent criss-cross merges.
- Zombieball 13y agoRun unit tests after rebasing & before pushing?
- mpyne 13y agoIf you require that each individual commit meets semantic criteria then you can still require that to occur during a git rebase by rewriting the commit. Which you should probably be doing anyways, if you're pulling breaking changes from upstream.
- ibrahima 13y agoExactly. It makes sense to rebase for a single commit or two when you're syncing with a remote frequently, but in any other case merge is much more sane.
- __david__ 13y agoHaving "git log -p" be readable is infinitely more important than so called "accurate" history.
- johnpmayer 13y agoIf you're going to rebase every pull, you may as well just use SVN.
- rcfox 13y agoGit has benefits over Subversion besides the crazy commit graphs. I'm not sure there's really any reason to be using SVN when you could be using Git in the exact same style, and have the benefit of offline access to the repository. Actually, I'd be interested in hearing about any sort of layers on top of git that make it work like SVN (ie: same commands, same workflow, etc.) It would probably help convince some people to move away from SVN.
- mh- 13y agosuch a layer would be difficult to provide in a way that isn't misleading, if the hypothetical subversion expatriate currently uses any functionality involving multiple (SVN) branches.
- ultimoo 13y agoWhile the idea of rebasing history while pulling in new changes may appeal to some users or uses, I disagree with the absolute "one true way" sounding note of OP's article. Git supports first class merging, and it is git's default behavior. It enables us to port over entire strings of commits related to a feature to other branches, or enables us to revert (un-merge) these strings of commits. Heck, --rebase doesn't even allow one to pull when there are uncommitted changes in the working directory. On the other hand, --rebase is neater when it comes to the modern mantras of "commit frequently", "no feature branches", "deploy master to production". So in short this sounds more like an editor or a tab v/s spaces flame war.
- dustingetz 13y agowhat's the idea behind no feature branches?
- jcoder 13y agoIf I understand GP, it's the idea that when your work on a feature branch is complete, you use rebase to base that branch on the current tip of the branch you are integrating to, e.g., "master", so the result does not reveal the presence of a branch.
- sanderjd 13y agoIf I understand the poster you're replying to, he understood that, but doesn't understand why you would want that. I'm in the same boat - why are people willfully throwing away useful history?
- andrewflnr 13y agoDefine "useful history". ;) There's history in the sense of "log of everything that happened" but also in the sense of a nice record of decisions that were made, documentation essentially. I'm guessing "no feature branches" aims more for the latter. Personally, I'm not sure why we shouldn't have both.
- pwim 13y agoRather than always using git pull --rebase you can set up your git config to always rebase when pulling. git config master.rebase true sets it up for master of the current repo git config --global branch.autosetuprebase always sets it up for all new branches.
- Osiris 13y agoI would argue that it's not a good idea to do this for all branches by default. For example, we do the opposite for 'master', we force merge commits (--no-ff) on master/integration branches but use pull --rebase on feature branches that we share.
- nahname 13y agoI would recommend that you do not do this. I rebase probably 80% of my pull requests, but sometimes you do want a merge commit. Instead, I setup an alias for git pull --rebase This also helps when pairing with someone else. The process of handling a rebase conflict vs pull/merge (regular pull) is quite different.
- wanderr 13y agoif you want to do a merge commit sometimes, but pull --rebase most of the time, why not make pull --rebase the default, and do a fetch && merge when that's what you want?
- Zombieball 13y agoBecause what if you 'already' created a merge? Example: I am working on a local branch feature/xyz. I decide I am done my work and merge feature/xyz -> master. I get ready to push and realize I am 5 commits behind origin/master. How do I fetch them now? If you use git --rebase it will clobber your feature branch merge commit. On the other hand if you do a fetch & merge this also probably is not what you want (you will have a merge-commit on top of your merge commit, dawg). git rebase -p is probably the best option in this scenario.
- zerohp 13y agoRebase only if you treat it like a centralized version control system. Using it all the time breaks a lot of good DVCS workflows.
- tootie 13y ago"to keep the repository clean" Seems like not a worthy objective. Has anyone here ever had a project saved by a tidy commit history?
- darrencauthon 13y agoTotally agree. At best this rebase talk is navel-gazing, and at worst it's a technique that turns Git into a complicated, scary place for those just want to get work done. I have introduced git and hg to many people, but I've always tried to tie it into what people do already. Without source control, practically everybody did the same thing: They'd work a little bit, they'd save, they'd work a little bit, they'd save... etc. Using branching for organizing work and a nice cheat-sheet of a few git commands, most non-technical people will be off-and-running. It all works until the programmers make it complicated with the rebasing. The price of the tidy commit history is the loss of confidence of the rest of the team. I'd rather have the people. Case in point: https://vimeo.com/60788996 https://vimeo.com/60788996
- base698 13y agoIt's only complicated because people don't realize how it works. Half the people in this thread advocating to use rebase aren't saying when it's ok and when it's not ok and why. When it's ok: You are working on your own line and the commits you've made are not in a central repo. Why: Git commits are a hash tree and when you change one commit it changes all the SHAs that come after it. This makes git see your commits pushed remote as different then the ones that are local. The commits have the same changes so it puts duplicate conflict markers everywhere. Most people love it once they realize how it works. A lot of people use version control also as a backup in case their hard drive fails. Because of this they are scared of staying on a topic branch for very long, so they push then rebase often leading to conflicts which are scary. https://en.wikipedia.org/wiki/Hash_tree https://en.wikipedia.org/wiki/Hash_tree
- ricardobeat 13y agoNot saved, but it adds up when you have a torrent of "Merge branch master of http://myownrepo.com http://myownrepo.com and merge conflicts every day.
- ricardobeat 13y agoBe careful though, rebase doesn't preserve merge commits. If you want to rebase after a merge you need git fetch && git rebase -p I recommend using git-up[1] which solves everything in a single command. [1] https://github.com/aanand/git-up https://github.com/aanand/git-up
- Zombieball 13y agoThis is very good advice! git --rebase will clobber local merge commits (e.g. when closing off a feature branch & getting ready to push the merged results). I threw together a quick custom action you can use with Sourcetree to utilize git rebase -p. Interested folks can nab it here: https://gist.github.com/dgourlay/5465540 https://gist.github.com/dgourlay/5465540 Install instructions here: http://www.derekgourlay.com/archives/478 http://www.derekgourlay.com/archives/478 I think I may need to give git-up a look over though. Thanks!
- jcrites 13y ago> local merge commits (e.g. when closing off a feature branch & getting ready to push the merged results Why not rebase the feature branch onto the master branch? Then the merge from feature to master will be a fast forward commit rather than a merge commit. Developing this way one can mostly avoid actual merges. And the repository history is simple and linear afterward. I've been working this way for a while and I have found it effective. % git checkout feature % git rebase master % git checkout master % git merge --ff-only feature (-ff-only isn't needed, but I like to confirm to catch mistakes) Any commits that you have made locally (and haven't pushed anywhere public) are safe to reorganize in this way, and it results in simpler history.
- ricardobeat 13y agoIf your workflow is based on very small feature branches, that's fine, but when your branch is more heavy on changes it's good to preserve the merge commit (and be able to undo it).
- redshirtrob 13y agoI like this philosophy for small, easily testable commits (e.g. minor bug-fixes). However, I never recommend others to use this workflow. I feel like rebasing is the type of feature you really need to understand to use. If you understand the concept and how to apply it, you can do powerful things. If you don't, you'll munge your repo and end up begging the local git guru to bail you out of your mess. While I don't enjoy looking at a commit history with a bunch of useless merges, it's better than encouraging users to perform an operation they don't understand.
- jen_h 13y agoNo kidding. Nothing makes you miss svn more than an inappropriate rebase. I've done it twice now, & sorely regretted. Heck, once, I was bit so badly by it that I actually said something positive about Rational Clearcase.
- mef 13y agoYes, exactly. And if your team consists of perhaps slightly less tech-oriented people (on our team it's the designers), trying to explain what rebase does and how to use it with its exceptions (the "Few notes though..." part of the article) is a recipe for confusion and broken repos. Which is why our policy is "rebase if you know what you're doing, otherwise merge".
- djbender 13y agoMislav has a great article on this topic: http://mislav.uniqpath.com/2013/02/merge-vs-rebase/ http://mislav.uniqpath.com/2013/02/merge-vs-rebase/
- orefalo 13y agoCan't agree more, I'll push it even further... Use G2! which does pull --rebase magically on your behalf. http://orefalo.github.io/g2/ http://orefalo.github.io/g2/ https://github.com/orefalo/g2 https://github.com/orefalo/g2
- benjamincburns 13y agoI humbly submit that this is a holy war. I personally am on the side of "history is just another part of the project to be maintained," but tread carefully friends; there's dogma at work here. On one hand it's good to preserve things exactly as they happened. How else will we blame Dumb Steve guilt-free when someone branches from an arbitrary hash to give a one-off release to an angry customer, thereby bifurcating the state handling logic that allows the machine to be certain that it's not emptying a crucible on a crate of orphaned puppies? Think of the puppies! On the other hand, it's good to align commits to units of work. It's cool that you've forked the project to handle massively concurrent input caused by edge case X (sorry, I used up most of my creativity on the last paragraph), but really I just want your cool configuration parsing piece. Can I cherry-pick that, please? Git was designed to give you the choice. Do you care about preserving the ability to perform an arbitrary audit, or do you care about treating development as a series of portable patches? You decide, and then do what's right for you.
- dscrd 13y agoOr just use mercurial which tends to do the Right Thing by default more often.
- lysium 13y agoIn what way do you think is mercurial's "Right Thing" a different "Right Thing" than what git does (by default)?
- dscrd 13y agoIn the way whereby nobody ever complains about usability issues like this one.
- Tomis02 13y agoMy first thought when I read the title was "Please use mercurial", because git is just a complicated tool that most of the time provides a distraction from real work (admittedly, a tool that gives a wonderful false sense of superiority - "zomg I am 3l1t3 h4x0r because I could finally persuade git to do what I want"). As a hg user I really can't have any understanding when I get git messages like "![rejected] master -> master (non-fast forward) error: failed to push some refs to ...". What the hell am I supposed to do with that? And a few minutes later I find out that in git you can't pull all the branches at the same time. Seriously, just use hg and make the world a better place.
- comex 13y agoThis has been mentioned in another comment, but not a top level one, so here it is again: Rebasing multiple commits means putting commits into the history that do not correspond to any actual historical version. If you manually test each commit to ensure that the merged version still compiles and runs, or you're sure that the changes don't conflict and don't get unlucky, then you have something akin to a patch set, a semantic rather than actual history that is easier to read and perform operations like git bisect on. But otherwise, you can end up with broken commits in the history that, when retrieved for bisection or other purposes, obscure whatever is actually supposed to be observed. Regardless of whether merging or rebasing produces 'better' history, if you're lazy, merging lets you stay that way without creating broken history.
- winstonchurch 13y agoThis is a TERRIBLE rule: they have no clue how git works. Read: http://goo.gl/ONw7Q http://goo.gl/ONw7Q
- mortehu 13y agoTo quote the page you linked: > People can (and probably should) rebase their _private_ trees (their own work).
- lurker14 13y agoIs coderwall some sort of troll site, like the the Swedish Lemon Angels recipe in How to Play With Your Food? I keep seeing bad advice posted there and popping up on HN.
- bnegreve 13y agoI try to avoid rebasing everything all the time because it changes the commit dates which can be confusing when you are tracking some particular changes.
- voyou 13y agoFrom the article: "When working on a project you usually synchronize your code by pulling it several times a day." Do you? Am I alone in thinking that seems like a really bizarre workflow?
- gurkendoktor 13y agoSometimes - why not? There are times when the client comes back with two dozen tiny feature requests. Fix one, push/pull, loop.
- khasinski 13y agoFrom my experience it is common for a group of developers co-working on some feature to share codebase very often. Also in an actively developed project there are likely to be many new commits every single day, and you want to be up to date with remote codebase to ease the pain of merging your features into it. If you rebase your work onto master often you'll greatly speed up the release of your feature when it is ready. You'll also avoid late surprises when something you depend on elsewhere in codebase change. You can also notify your co-workers about inconsistencies between developed features and detect incompatibilities early. It also works in macro scale - projects released often with small changes shorten the feedback loop and can be adjust properly for their requirements.
- stasm 13y agoThere is history and there is cleanness, as Linus Torvalds explained in http://lwn.net/Articles/328438/ http://lwn.net/Articles/328438/. The git way of doing what the OP wants to do is to develop all code on local branches. They're cheap and you can have as many of them as you want. Just never commit directly to master and set it to track upstream/master. Synchronize with upstream by pulling into your local master, and then rebase, merge & diff your local branches at will.
- oneandoneis2 13y agoUm.. No.. if you use rebase regularly, you're doing something very wrong. In this case, the problem is that development isn't being done on a branch. One of the most important features of Git is how easy it is to fork & merge - there's no excuse for doing your work on master. Work on a branch, merge your branch into master when it's finished. History is completely accurate, you only get one merge commit. Don't mess up history just to work around bad workflow. Fix the problem at its source.
- eloisant 13y agoIndeed when you do work on a feature branch, you shouldn't rebase. But when you're working on master, or a branch that's also remote, then you have to rebase. If you don't then you get completely meaningless merge commits. If 3 people merge when they just want to push a commit it then you're history becomes a tangled unusable mess.
- justin_vanw 13y agoMaybe you are history becomes a tangled unusable mess, but it works for me just fine.
- Cthulhu_ 13y agoThen those three should've worked on their own feature branch. In fact, one could consider a local copy of master (or, commits made on master on one user's machine) as a feature branch, all named 'master'. Another thing, a developer doesn't need to obsessively pull every couple of minutes. If they're fixing a bug and deciding against using a branch for that (seeing that it could be just one commit), they only pull twice; once before they start working, and again when they're done and want to push to master. If there's more than one person fixing the same bug simultaneously, then it's yet another process bug.
- reledi 13y ago> In this case, the problem is that development isn't being done on a branch. Huh? Do you mean it isn't being done on a topic (aka feature) branch? Master branch is still a branch. > there's no excuse for doing your work on master. Many people, including myself, aren't going to create a new topic branch for drive-by commits, such as fixing a typo. > Work on a branch, merge your branch into master when it's finished. ... Don't mess up history just to work around bad workflow. You're technically rewriting history, but it's not like you're rewriting history that's been pushed (which is typically a big no-no). Many people prefer a cleaner, more linear history from rebasing. And if you're implying that using topic branches somehow fixes the "problem" of having to rebase, that's not true. If you've pushed your topic branch to a remote git repo then anyone else with commit access can make changes or you can even make changes on the remote repo if the web interface allows it (like how GitHub does).
- justin_vanw 13y agoRebase is nice if you have very careful code review policies. Otherwise, if you don't have humans carefully reading every merge, it is a huge waste of time. Rebasing also increases the number of conflicts you will have to resolve. I've seen this 'always rebase' advice over and over in the last few years, it's stupid advice that betrays a lack of understanding about how git works. There is no advantage whatsoever unless you also squash your commits, and even then there is no advantage unless you are submitting to a project with very careful code review practices (Linux kernel, a project that uses the gerrit code review tool, etc).
- jayferd 13y agoI've been telling people lately to always fetch and merge --ff-only separately, which is more commands but less confusing behavior. If you've got merge.defaultToUpstream set to true, you can alias ff = merge --ff-only. That way you can be careful about rebases, and don't have them automatically happening behind your back. So the workflow is: % git fetch # can never fail with a conflict % git ff # tries to fast-forward # if fast-forward fails, then % git rebase origin/upstreambranch
- rachbelaid 13y agowhy not changing your config for the no-feature branch to avoid that people forgot the --rebase arguments git config branch.master.rebase true git config branch.develop.rebase true This will make any pull be a pull --rebase on the master/develop
- khasinski 13y agoOP here, I do prefer feature branches (especially git flow: https://coderwall.com/p/d1pkgg https://coderwall.com/p/d1pkgg ), but for day to day 'agile' development in a small team we don't use them often. YMMV. But for pulling changes working on local branch git pull --rebase (or autorebased branch) is many times more readable (and avoid ugly merge bubbles in history). Branch when you need branches, merge when you mean merging, rebase when you're just updating your codebase from shared repository. Keep your local (not pushed/pull-requested yet) branches dirty (commit often!), rebase them into a clean, obvious history before you share them. Remember - commit history is for other people to READ.