Use of git rebase in public feature branches
Asked Answered
B

3

36

You can see all over the web people advising to not use git rebase in a public branch, but I can't see what's the problem, if you always rebase a feature branch.

My team always uses branches for features (wow), we are used to have it just locally, so rebase isn't a problem, but sometimes we wanna show the code of a partially done feature to another developer, so we just publicize it, but then we lose all of the advantages of git rebase, or at least that's what you can read at the web.

I don't understand what's the problem, if the developers working at the same public branch never merge it to any branch (when there is still development on that branch) and when they pull it, they do it with a rebase operation. Any changes made to the branch will be always rebase on top of the remote branch, so never lost and you won't have the problem of having the same commit duplicated.

Append 1:

None of the answers until now showed the problems that will happen and how it will happen, so I will try to be clearer.

I will give an example of a workflow using rebase (badly described in the previously paragraphs, sorry) that I don't see any problem.

Initial state:

master         ==========A
origin/feature           +=====AB
feature user A           +=====AB
feature user B           +=====AB

master get a few commits and user A does a few commits:

master         ==========A=====C
origin/feature           +=====AB
feature user A           +=====AB====D
feature user B           +=====AB

User A does a git pull --rebase (he always does it) to update his branch, nothing new comes, then he rebase to master and push:

master         ==========A=====C
origin/feature                 +=====ACB'=====ACB'D
feature user A                 +=====ACB'=====ACB'D
feature user B           +=====AB

(notice the B' is the new commits that still represents the changes B)

Then user B does a few commits:

master         ==========A=====C
origin/feature                 +=====ACB'=====ACB'D
feature user A                 +=====ACB'=====ACB'D
feature user B           +=====AB======E

User B finally does a git pull --rebase as always, there is no need to rebase on master, so he just pushes:

master         ==========A=====C
origin/feature                 +=====ACB'=====ACB'D======E'
feature user A                 +=====ACB'=====ACB'D
feature user B                 +=====ACB'=====ACB'D======E'
Boykins answered 12/1, 2010 at 4:0 Comment(3)
The problem in "Append 1" is that once user B does git pull --rebase his B' will be different from user A's B' because each variant of commit B' contains a commit timestamp which changes respective SHA-1 hash of each commit. If neither user A nor user B never changes any patch and rebase always gets done without conflicts, you can mostly get away with the difference in the SHA-1 as long as you always rebase on top of the master instead of merging into master. If all your git users are aware of the situation, go for it.Foolhardy
@MikkoRantalainen, that's not true. The timestamp is preserved. But you're right when there are conflicts, user A may solve conflicts different from user B and this would produce different commits (different SHAs), breaking everything. That was the answers I was expecting almost 4 years ago. I would be glad to accept it if you write as an answer.Boykins
A Git commit contains always two timestamps that both affect the SHA-1 for the commit: "author" timestamp and "committer" timestamp (both with 1 second granularity; try git cat-file -p HEAD for an example). Both can be overridden while creating a commit, but by default for new commits, both have the current time. For rebased commits, "Author" timestamp is kept intact and "Committer" timestamp is set to the time of the rebasing. Unless you use special flags for the rebase, your rebased SHA-1 depends on the time you run the rebase command.Foolhardy
T
41

If you rebase, you rewrite history. And just like in the real world, if you want to rewrite history, you need a conspiracy: everybody has to be "in" on the conspiracy (at least everybody who knows about the history, i.e. everybody who has ever pulled from the branch).

As long as the circle of people who pull from the branch is tightly controlled, it is fairly easy to get a conspiracy going, however, as soon as you publish that history, it becomes a lot harder. It's not impossible, though: the pu branch in Junio C Hamano's Git repository for example, gets rebased after every release, and that is a widely published repository. The way this works is that the fact that the branch will be frequently rebased and the times when that will happen, are widely documented on the Git website, the Git wiki and the Git mailinglist, and every rebase is announced on the mailinglist in advance so that people can prepare for it.

Thermotaxis answered 12/1, 2010 at 4:40 Comment(5)
Exactly. The point is that anyone that uses (or might use) a branch must be told whether its history might eventually be rewritten. As long as you have agreement from all the (potential) users, there is nothing wrong with rewriting published history. A users' agreement indicates that they have no right to complain when you rewrite that branch's part of history. You might even use a special prefix to indicate such rewritable branches: tmp/, unstable/, rewritable/, or use-at-own-risk/.Pleistocene
I don't think it needs a conspiracy, I improved my question to have an example of a workflow that don't need it.Boykins
so as long as you can get everybody in on the conspiracy, what are the steps to make sure they get synced up with the rewritten history?Barr
For future reference: How to recover from an upstream rebase is covered e.g. by git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase (and also, partly, by git-scm.com/book/en/v2/…).Almsgiver
Did you read Orwell's 1984? There's a great example of rebasing gone wrong.Yerga
C
7

When you rebase against public branch, it's perfectly ok.

But when you rebase public branch itself, it is not good for people which are also working with it.

Addition:

When rebase breaks unittest, you won't have an opportunity to git bisect the faulty revision.

In more details:

  • you have prepared some code to be added to the branch.
  • you have debugged it so it passes all unit tests
  • you've git-fetched new changes in the (remote) branch
  • now you're rebasing your code against rebased remote branch
  • and here unittests get broken
  • you're running git bisect and it points at the remote rebase.
  • your actions?
Candelabrum answered 12/1, 2010 at 4:4 Comment(2)
Isn't that because you would have a different history to that of the others, thus confusing attempts to sync your repos?Foxworth
My actions: Check why it brokes and fix the commit, is that too hard? The same will happen if you merge and the tests were OK for the 2 parents of the merge but not for the merge commit.Boykins
G
5

http://git-scm.com/book/ch3-6.html

Under the section called "Perils of rebasing"

...you’ll be scorned by friends and family.

Giacometti answered 14/6, 2013 at 19:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.