Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Reordering history can accidentally "merge" an intermediate PR in `--direct` mode

Closed
#367 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Active
Tech stack
git, github, python
Domain
cli

Research direction

Reproduce the failure with the supplied foo.sh script, using ghstack --direct and repeated interactive reordering against origin/main. Trace the stack update and GitHub PR status changes involved in the reordering; done means swapping the second and third commits repeatedly no longer marks an intermediate PR as merged.

Written by the indexing model from the issue text.

Description

Haven't put a lot of time into understanding this one, was just trying to evaluate ghstack for work on LLVM. The issue was that while editing and reordering commits, one of their PRs was automatically marked "Merged", when I had not merged anything. I assume this is due to the lack of an atomic way to update base branches for several PRs at once, but unsure the exact cause.

Simplest way to reproduce turned out to be to just swap the position of two commits in a stack repeatedly:

#!/bin/bash

stack() {
  ghstack --direct || return 1
  # attempt to rule out racing against a slow GH or something, doesn't seem to
  # matter, and I hit the bug originally while just using the tool by-hand
  #sleep 10
}

swap2() {
  # swap the 2nd and 3rd `pick` lines in the interactive rebase buffer
  GIT_EDITOR='printf "%s\n" 2y 2d x w | ed -s' git rebase -i origin/main
}

init() {
  for n in $(seq 4); do
    echo $n >> $n && git add -A && git commit -m $n || return 1
  done
}

whirl() {
  # seems to pretty regularly break on round 3, but add plenty to be sure.
  # not actually clear to me if this is deterministic or not
  for n in $(seq 10); do
    stack && swap2 || {
      printf 'failed on round %d\n' $n
      return 1
    }
  done
}

main() {
  init && whirl
}

"$@"

Can run as foo.sh main to have it build a short stack and then start swapping and restacking until it breaks.

If there is more info I can share, let me know. I only spent enough time to be sure I wasn't just holding it wrong.

Dominant language
Python
Stars
1k
Forks
84
Avg merge
10m
Merged PRs (30d)
1

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ezyang/ghstack

All issues in ezyang/ghstack

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.