11

When I'm working on a feature branch, I tend to want to cleanup the commits in the branch using an interactive rebase before my work is reviewed and integrated in the main branch.

During development of the feature, I want to push my intermediate work to the remote repository as a backup measure. I.e. when my hard-drive crashes, I don't want my entire feature branch to be lost.

However, this leads to the fact that I often have to do a git push --force to the remote repository after a rebase, an action which is generally frowned upon. Or as the linked github page says:

Because changing your commit history can make things difficult for everyone else using the repository, it's considered bad practice to rebase commits when you've already pushed to a repository.

Is there a (generally accepted) policy that solves this conflict?

Why this is not a duplicate of Is the git "Golden Rule of Rebasing" so essential?

My question here asks for a policy to solve the conflict between wanting to backup your work in the remote repository and rebasing your work, while the other question tries to deny that there is a conflict and asks why some people think the conflict exists at all, and thus asks why "it is essential" not to push force rebases?

  • 1
    Possible duplicate of Is the git "Golden Rule of Rebasing" so essential? – gbjbaanb Mar 14 '16 at 13:45
  • 1
    @gbjbaanb if you make WIP commits, a rebase is very useful to avoid having many commits for a single days worth of work. I often make commits for small changes just so I have a "undo to a state I remember" option if needed - most of these are irrelevant/noise to the main history of the repo (which is why rebase is so useful). – enderland Mar 14 '16 at 13:52
  • 1
    @gbjbaanb That's a matter of opinion I think. Many teams use a rebasing strategy to keep their history clean. – Chiel ten Brinke Mar 14 '16 at 13:52
  • 1
    @enderland everyone wants pretty history, its still the wrong (and dangerous) thing to do as shown by the link. Torvalds should never have put it in, he should have allowed commits to be "compressed" on display instead. – gbjbaanb Mar 14 '16 at 13:53
  • 1
    @gbjbaanb but... he didn't, and so we have to work with what we have. To me it is far more useful to have a single commit on the master branch instead of 30+ individual and incremental commits from each feature branch. But everyone will have a different workflow, I guess... – enderland Mar 14 '16 at 13:54
5

The key question to ask yourself:

  • Do you keep your remote branch after merging back into master?

If you delete your remote feature branch after merging into master, you already are losing the history. Assuming you squash/rebase the branch prior to making your merge/PR you lose this history. All your force push is doing in this case is allowing you to use github as a backup.

The situation where you would want to keep the history and not force push is if your remote branch is persisting after being merged and not only existing for a temporary period of time.

I suppose you're asking if I would keep the unrebased branch? No, AFAIC. Still, push forcing it might theoretically result in loss of commits from other users who pushed to the same branch

It sounds like you have multiple people pushing to that branch simultaneously. This means you do care about the history on the branch.

What you could do instead for your intermediate work is create a fork of that branch. You can push to this and then rebase all your commits into a single commit prior to merging, so when you merge them into your feature-branch, you only have 1 commit (with the rebased history of your entire branch).

  • "Do you keep your remote branch after merging back into master?" I suppose you're asking if I would keep the unrebased branch? No, AFAIC. Still, push forcing it might theoretically result in loss of commits from other users who pushed to the same branch. – Chiel ten Brinke Mar 14 '16 at 15:15
  • @ChieltenBrinke I edited a bit about that. FYI – enderland Mar 14 '16 at 15:51
  • I think that forking as a measure to prevent destroying commits when push forcing is actually a very good suggestion. But AFAIK it is not really a git concept, and you need a service wrapper around that to do this easily (such as github). Am I correct about that? Or maybe I mistake your use of the term "forking" for just creating a seperate branch? – Chiel ten Brinke Mar 14 '16 at 15:56
  • @ChieltenBrinke well you can accomplish the same thing in a variety of ways. If your feature branch is on the remote repository, you can fork the repo and have your version of that branch. And then merge that branch into your remote branch after squashing commits. Or you can just create a different local branch (maybe featurebranch-local) and then do active dev on that branch, with as many commits as you want. Once you want to merge, squash those commits and then merge them into the feature. Basically just doing dev in an actual temporary branch and then squashing/merging into your feature. – enderland Mar 14 '16 at 16:00
  • Assuming that forking a repo is out of option because one doesn't use github, we would work with a "private" develop-feature branch. Of course the privateness is purely by convention and not enforced by anything, but can be made part of a policy, especially if certain branch naming conventions are introduced for this. (Maybe I'm being too anxious right now, maybe not :) The combination with --force-with-lease can't hurt, though shouldn't be relied upon, as pointed out in my other post. – Chiel ten Brinke Mar 14 '16 at 16:19
3

I'm listing some possibilities here that cross my mind.

Always rebase on a new branch

When having a messy branch some-feature, rebase it on a new branch. E.g.

$ git checkout -b some-feature-rebase
$ git rebase -i master # etc..

Then have some-feature-rebase reviewed and integrated.

Problem: A big downside here is that, strictly speaking, you need a new branch for every rebase. (You could have multiple rebases if you make changes after a code review, for instance)

Use git push --force-with-lease

I just learned about the git push --force-with-lease alternative to git push --force, which

refuses to update a branch unless it is the state that we expect; i.e. nobody has updated the branch upstream.

Problem: This seems to improve directly upon the situation where we use just --force, but still has some caveats, most notably when I do a git fetch instead of a git pull, which updates our local upstream branches, tricking --force-with-lease into thinking that no unmerged changes were made on the remote branch.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.