-
Notifications
You must be signed in to change notification settings - Fork 75
Don't unexpectedly merge when commits are reordered #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Given the issues shown by |
|
So, while I agree that rINI2 not showing up in the final merge graph in To state the problem differently: previously, ghstack tried to accurately represent the rebase workflow as a series of incremental merges. But if I do an interactive, reordering rebase, what is the desired mergey version of the history? Rebase A1 and B1 onto M2: Reorder A1 and B1 I'd argue that there is just no way to do it in the merge only view fo the universe, so we might as well not even try. A simple patch to solve the "but I want master commits to be reachable" might just be to add an extra master merge base if you detect that master has advanced in the rebased stack but the merge base isn't there yet. But remember that this merge base is still going to be inaccurate if you rebase your commits backwards in time! |
|
@ezyang That makes sense I think; I'm still pondering your second example but I see the gist of what you're saying. What I've been wondering is: assuming that it's not possible to always construct a consistent mergey history, why not just use an actual stack of commits (e.g. have |
|
The keyword here is "force push" :) If we force push, GitHub loses track of all the previous commits (they no longer show up in the PR description page). By never force pushing, we can maintain consistent history. |
|
@ezyang Makes sense to me. So, should we merge this PR as-is? |
|
I guess we might as well dogfood it for a while and see if it works. |
|
@ezyang Thinking about this more, I actually think we do want to put in some additional logic to allow rebasing onto a more recent version of |
|
Err, people don't ever actually attempt merges on the head branch, it's just to make GitHub happy. |
|
Ah, I see what you mean; makes sense! |
|
It turns out, while HUMANS don't merge with master, CI SCRIPTS do. Test failures at https://app.circleci.com/pipelines/github/pytorch/pytorch/285473/workflows/5709135d-0ef7-448f-8757-fde30622f343/jobs/11551386 due to inaccurate master information |
Closes #23.
Let's say we have a stack with two commits (listed here in reverse chronological order):
gh/user/Ygh/user/XLet's say that
origin/gh/user/Y/baseis out of date, and we runghstackto update these on GitHub.origin/gh/user/Y/baseis an ancestor of (local)gh/user/X/head, then we updateorigin/gh/user/Y/baseto begh/user/X/head. Otherwise, we updateorigin/gh/user/Y/baseto be a merge commit whose parents are:origin/gh/user/Y/basegh/user/X/headorigin/gh/user/Y/baseis not equal togh/user/X/head, we updateorigin/gh/user/Y/baseto be a new commit whose only parent is (the previous)origin/gh/user/Y/base.This reduces the number of cases in which
basecommits end up as descendants forheadcommits from other parts of the stack.This PR adds
test_ghstack.py::TestGh::test_reorderto check a commit reordering scenario similar to the one given in the linked issue. In the test, this is the repository state before reordering:If you run the test without the changes introduced in this PR, this is what the final "Repository state" looks like:
The order of operations to get to this point is important:
ghstackghstackpushes thebasebranches firstghstackpushes theheadbranchesghstackpushes theorigbranches (not shown here)This means that after step 2 (but before step 3), we have the following:
gh/ezyang/1/headpoints torMRG1gh/ezyang/1/basepoints torMRG2ABut
rMRG1is an ancestor ofrMRG2A! Thus from GitHub's perspective,gh/ezyang/1/headhas been merged intogh/ezyang/1/base, so it marks the PR as merged. Updatinggh/ezyang/1/headafter this point doesn't actually do anything to the PR.In contrast, this is the final repository state of the test using the changes in this PR:
As shown, neither new
basecommit is a descendant of its respective formerheadcommit, so neither PR gets prematurely marked as merged.This PR also changes a few existing tests in
test_ghstack.py::TestGh:test_amend_bottomtest_amend_alltest_rebasetest_cherry_picktest_remove_bottom_commitMost of these seem fine, but the
test_rebaseandtest_cherry_pickchanges are a bit concerning, because the result is that after we updatemaster, the updatedmastercommit still isn't actually an ancestor of ourbaseorheadbranches.