diff --git a/src/ghstack/submit.py b/src/ghstack/submit.py index f7910c5..aefc717 100644 --- a/src/ghstack/submit.py +++ b/src/ghstack/submit.py @@ -1374,6 +1374,7 @@ def _create_non_orig_branches( push_branches.head.commit is None or updated_base or push_branches.head.commit.tree != diff.tree + or self.no_skip ): new_head = GitCommitHash( self.sh.git( diff --git a/src/ghstack/test_prelude.py b/src/ghstack/test_prelude.py index a21ebcd..f4bfc55 100644 --- a/src/ghstack/test_prelude.py +++ b/src/ghstack/test_prelude.py @@ -189,9 +189,11 @@ def gh_submit( update_fields: bool = False, short: bool = False, no_skip: bool = False, + force: bool = False, base: Optional[str] = None, revs: Sequence[str] = (), stack: bool = True, + check_invariants: bool = True, ) -> List[ghstack.submit.DiffMeta]: self = CTX r = ghstack.submit.main( @@ -204,6 +206,7 @@ def gh_submit( repo_owner_opt="pytorch", repo_name_opt="pytorch", short=short, + force=force, direct_opt=self.direct, no_skip=no_skip, github_url="github.com", @@ -211,9 +214,10 @@ def gh_submit( base_opt=base, revs=revs, stack=stack, - check_invariants=True, + check_invariants=check_invariants, ) - self.check_global_github_invariants(self.direct) + if check_invariants: + self.check_global_github_invariants(self.direct) return r diff --git a/test/submit/amend_message_only.py.test b/test/submit/amend_message_only.py.test index c909511..36bf530 100644 --- a/test/submit/amend_message_only.py.test +++ b/test/submit/amend_message_only.py.test @@ -16,11 +16,14 @@ if is_direct(): This is commit AAA + * 1774f4b Update A * 5cd944b Initial 1 Repository state: - * 5cd944b (gh/ezyang/1/next, gh/ezyang/1/head) + * 1774f4b (gh/ezyang/1/next, gh/ezyang/1/head) + | Update A + * 5cd944b | Initial 1 * dc8bfe4 (HEAD -> master) Initial commit @@ -36,11 +39,14 @@ else: This is commit AAA + * fa3f7db Update A * 1081a5b Initial 1 Repository state: - * 1081a5b (gh/ezyang/1/head) + * fa3f7db (gh/ezyang/1/head) + | Update A + * 1081a5b | Initial 1 * 5a32949 (gh/ezyang/1/base) | Initial 1 (base update) diff --git a/test/submit/no_skip_fixes_remote.py.test b/test/submit/no_skip_fixes_remote.py.test new file mode 100644 index 0000000..9359246 --- /dev/null +++ b/test/submit/no_skip_fixes_remote.py.test @@ -0,0 +1,78 @@ +from ghstack.test_prelude import * + +init_test() + +commit("AAA") +(A,) = gh_submit("Initial") + +# Record the correct state before corruption +correct_head = git("rev-parse", "origin/gh/ezyang/1/head") + +# Corrupt the remote head branch by pushing a wrong commit to it +# We'll push an unrelated commit (just the tree, no proper parents) +corrupted_commit = git("commit-tree", git("rev-parse", "master^{tree}"), "-m", "Corrupted") +git("push", "origin", "--force", f"{corrupted_commit}:gh/ezyang/1/head") + +# Verify the branch is actually corrupted +assert git("rev-parse", "origin/gh/ezyang/1/head") == corrupted_commit + +# Now submit with --no-skip --force and no local changes +# This should fix the corrupted remote branch +(A2,) = gh_submit("Fix", no_skip=True, force=True, check_invariants=False) + +# Verify the head branch was restored to a valid state +# It should have been updated (new commit), not rolled back +fixed_head = git("rev-parse", "origin/gh/ezyang/1/head") +assert fixed_head != corrupted_commit +assert fixed_head != correct_head # Should be a new commit due to --no-skip + +# Verify that the diff between head and base matches the diff in orig +# This ensures the fix properly maintains diff integrity +if is_direct(): + head_base_diff = git("diff", "origin/master", "origin/gh/ezyang/1/head") +else: + head_base_diff = git("diff", "origin/gh/ezyang/1/base", "origin/gh/ezyang/1/head") +orig_diff = git("diff", "origin/gh/ezyang/1/orig~", "origin/gh/ezyang/1/orig") +assert head_base_diff == orig_diff, "head/base diff should match orig/orig~ diff" + +if is_direct(): + assert_github_state( + """\ + [O] #500 Commit AAA (gh/ezyang/1/head -> master) + + This is commit AAA + + * 889632c Fix + * 94870d6 Corrupted + + Repository state: + + * 889632c (gh/ezyang/1/next, gh/ezyang/1/head) + | Fix + * 94870d6 + Corrupted + """ + ) +else: + assert_github_state( + """\ + [O] #500 Commit AAA (gh/ezyang/1/head -> gh/ezyang/1/base) + + Stack: + * __->__ #500 + + This is commit AAA + + * 889632c Fix + * 94870d6 Corrupted + + Repository state: + + * 889632c (gh/ezyang/1/head) + | Fix + * 94870d6 + Corrupted + """ + ) + +ok()