So I have a rebase vs pull question: Lets say I have a PR, if I merge that to my local tree using "git pull --rebase remote-repro branch-name" then I get a nice clean history locally without those pesky merge commits cluttering everything up. But... Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch? Still don't understand Git yours, John.
On 16/04/15 14:00, John Maddock wrote:
Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch?
This is exactly what I warned about couple of days ago in boost-build list. Doing rebase you edit history, which is dangerous operation by definition. I understand why you guys want to see plain clean history - but this is wrong in most cases. Think about it - real history _is_ _not_ _plain_ in case of distributed development, but you're trying to make it plain (i.e. rewrite). Such rewriting may work without problems in trivial cases, but generally you shouldn't expect it would be always smooth. I'll try to explain it. If Alice and Bob started from some commit C and did several commits in their local repositories, they already have two different histories. Now, if they want contribute their changes back to upstream, first one (Alice) just push to remote branch, and remote history becomes like below (left-to-right): -*-*-C-*-*-*-A (here A is Alice's top commit) Now Bob want commit too, but his local history looks like this one: -*-*-C-*-*-*-B (here B is Bob's top commit) So Bob has two choices. First - merge remote branch to his local and push back merged changes (default git behavior). Final history will look then like this one: -*-*-C-*-*-*-A-M(here M is newly added "merge" commit) \ / *-*-*-B Second choice: rebase his history on top of current remote HEAD. History will be plain then: -*-*-C-*-*-*-A-*-*-*-B This looks good, right? But think about two things: (a) what if rebase will not be smooth and there would be conflicts in process of rebasing? Git will break rebasing on first conflict (i.e. somewhere in middle of process) and you'd be enforced to fix it manually. On this step you should be _very_ concentrated to fix it and resume rebasing process properly, because otherwise you can easily corrupt anything (accidentally throw away several commits, for example). (b) what if Bob's commits depends on something which was broken in Alice's history? If history was merged, Bob (or someone else) can easily revert merge commit, fix issue in Bob's or Alice's local branch, and then merge again - without worrying other developers. In case of rebase, Bob (or someone else) enforced to revert all Bob's (or all Alice's) commits one-by-one (in proper order!), making history much more dirty; or, alternatively, all other developers would wait while Bob fix bug and make one more commit to the common repository. Shortly speaking, if you're doing rebase, you must know what you're doing, because it's dangerous. Otherwise you'll break something, sooner or later. -- Dmitry Moskalchuk
On 04/16/2015 02:00 PM, John Maddock wrote:
So I have a rebase vs pull question:
Lets say I have a PR, if I merge that to my local tree using "git pull --rebase remote-repro branch-name" then I get a nice clean history locally without those pesky merge commits cluttering everything up. But...
Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch?
What I do, for pull requests, is either:
git fetch
On 16/04/2015 23:00, John Maddock wrote:
So I have a rebase vs pull question:
Lets say I have a PR, if I merge that to my local tree using "git pull --rebase remote-repro branch-name" then I get a nice clean history locally without those pesky merge commits cluttering everything up. But...
Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch?
"git pull --rebase" is for updating "feature" branches -- ie. it's what the submitter of the PR would do on the PR branch itself to incorporate changes made on the parent branch (eg. "develop") into the PR branch, to make it easier to merge. You should never ever run that command on your mainline branches (master and develop). If you want to merge a PR without a merge commit, then you should cherry-pick it, as others have said. It's not unreasonable to have a merge commit in this case, though, since you are merging some third-party work. Typically the case where you want to avoid merge commits is when you're doing work yourself on a local feature branch. Also note that Github has convenience tools for automatically merging PRs, although the downside of that is that you don't get to test the results before they end up on your mainline branch.
Am 17.04.2015 12:52 vorm. schrieb "Gavin Lambert"
On 16/04/2015 23:00, John Maddock wrote:
So I have a rebase vs pull question:
Also note that Github has convenience tools for automatically merging
PRs, although the downside of that is that you don't get to test the results before they end up on your mainline branch.
That can be easily accomplished with travis-ci or circle-ci. I prefer the latter, tight docker integration and no time limit.
_______________________________________________ Unsubscribe & other changes:
On 16/04/2015 23:52, Gavin Lambert wrote:
On 16/04/2015 23:00, John Maddock wrote:
So I have a rebase vs pull question:
Lets say I have a PR, if I merge that to my local tree using "git pull --rebase remote-repro branch-name" then I get a nice clean history locally without those pesky merge commits cluttering everything up. But...
Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch?
"git pull --rebase" is for updating "feature" branches -- ie. it's what the submitter of the PR would do on the PR branch itself to incorporate changes made on the parent branch (eg. "develop") into the PR branch, to make it easier to merge.
You should never ever run that command on your mainline branches (master and develop).
Indeed, and I've found a way to do what I want: 1) Create a temporary local branch off develop and switch to it. 2) Merge the PR using git pull --rebase: now the PR commit is somewhere in the commit history prior to your last commits. 3) Revert the tree to the last commit from the PR. 4) Merge from develop using rebase - now the commits will be swapped round so the PR ends up at the end of the commit log. 5) Test. 6) Merge temp branch into develop: you should now have a clean history in develop with the PR commits at the end. 7) Delete the temp branch. Cheers, John.
That is very helpful because I have not been able to find out how to do this. As a newish (1 year) maintainer of Boost Phoenix I have had to search around for the things which need to be done occasionally. What would help me even more is the exact command for this one in your sequence: 2) Merge the PR using git pull --rebase: now the PR commit is somewhere in the commit history prior to your last commits. Could you give an example of what the command will be and where to find the information needed to put it together? When I have found out more I hope to put together a training manual for maintainers, so that we have one place to find all that we need. Thanks John ________________________________________ From: Boost [boost-bounces@lists.boost.org] on behalf of John Maddock [jz.maddock@googlemail.com] Sent: 22 April 2015 19:11 To: boost@lists.boost.org Subject: Re: [boost] [Git] Pull requests and rebasing On 16/04/2015 23:52, Gavin Lambert wrote:
On 16/04/2015 23:00, John Maddock wrote:
So I have a rebase vs pull question:
Lets say I have a PR, if I merge that to my local tree using "git pull --rebase remote-repro branch-name" then I get a nice clean history locally without those pesky merge commits cluttering everything up. But...
Now I can't fast-forward when I push to the remote, *because I've changed the existing history of the develop branch*. Would this not be a) bad form, and b) potentially dangerous to push to the remote develop branch?
"git pull --rebase" is for updating "feature" branches -- ie. it's what the submitter of the PR would do on the PR branch itself to incorporate changes made on the parent branch (eg. "develop") into the PR branch, to make it easier to merge.
You should never ever run that command on your mainline branches (master and develop).
Indeed, and I've found a way to do what I want: 1) Create a temporary local branch off develop and switch to it. 2) Merge the PR using git pull --rebase: now the PR commit is somewhere in the commit history prior to your last commits. 3) Revert the tree to the last commit from the PR. 4) Merge from develop using rebase - now the commits will be swapped round so the PR ends up at the end of the commit log. 5) Test. 6) Merge temp branch into develop: you should now have a clean history in develop with the PR commits at the end. 7) Delete the temp branch. Cheers, John. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 23/04/2015 06:11, John Maddock wrote:
On 16/04/2015 23:52, Gavin Lambert wrote:
"git pull --rebase" is for updating "feature" branches -- ie. it's what the submitter of the PR would do on the PR branch itself to incorporate changes made on the parent branch (eg. "develop") into the PR branch, to make it easier to merge.
You should never ever run that command on your mainline branches (master and develop).
Indeed, and I've found a way to do what I want:
1) Create a temporary local branch off develop and switch to it. 2) Merge the PR using git pull --rebase: now the PR commit is somewhere in the commit history prior to your last commits. 3) Revert the tree to the last commit from the PR. 4) Merge from develop using rebase - now the commits will be swapped round so the PR ends up at the end of the commit log. 5) Test. 6) Merge temp branch into develop: you should now have a clean history in develop with the PR commits at the end. 7) Delete the temp branch.
Admittedly I mostly use TortoiseGit, so I'm a little unfamiliar with the command-line, but that seems more complex than it needs to. 1. Create a local branch with a copy of the PR (assuming it's on GitHub): git fetch origin pull/PR#/head:branchname git checkout branchname 2. Do any initial testing that you want -- it should be in the same state that the submitter left it. 3. "git rebase --interactive develop" to rebase the changes onto the current develop branch (avoiding a merge commit). 4. Test the new result. 5. Merge the temporary branch into develop. (Optionally with --squash, if you want to compress multiple commits into one -- but then you have to remember to commit again afterwards.) 6. Delete the temporary branch.
participants (6)
-
Dmitry Moskalchuk
-
Fletcher, John P
-
Gavin Lambert
-
John Maddock
-
Thomas Heller
-
Vladimir Prus