Skip to content

Commit b6a9c59

Browse files
Name the pull request's branch, and abort a conflicting merge first
The Action named its local copy of the pull request pr-<number>, so the comment read "git merge pr-1". It now uses the pull request's own branch name, falling back to pr-<number> when that name is the base's or one git won't take. For a merge that will conflict, pre-flight advised resetting away a merge commit that git never makes, since it stops at the conflict. It now says git merge --abort puts everything back, and how to undo the merge once it's resolved and committed. Signed-off-by: Jacob Stopak <jacob@initialcommit.io>
1 parent a86601e commit b6a9c59

3 files changed

Lines changed: 30 additions & 7 deletions

File tree

‎integrations/github-action/action.yml‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,35 +54,44 @@ runs:
5454
run: python -m pip install --quiet "$PACKAGE"
5555

5656
- name: Fetch the pull request and its base
57+
id: fetch
5758
shell: bash
5859
env:
5960
BASE: ${{ github.event.pull_request.base.ref }}
6061
NUMBER: ${{ github.event.pull_request.number }}
62+
HEAD_REF: ${{ github.event.pull_request.head.ref }}
6163
run: |
6264
set -euo pipefail
63-
# The pull request's commits as a branch git-sim can name. The base is
64-
# fetched apart from it: on pull_request_target the checkout is the base
65-
# branch itself, which git refuses to fetch into.
66-
git fetch -q origin "+refs/pull/$NUMBER/head:refs/heads/pr-$NUMBER"
65+
# The pull request's commits as a local branch named like its own, so
66+
# the report says "merge feature"; pr-<number> when that name can't be
67+
# used (a fork's main into main, or a name git won't take)
68+
BRANCH="$HEAD_REF"
69+
if [ -z "$BRANCH" ] || [ "$BRANCH" = "$BASE" ] || ! git check-ref-format --branch "$BRANCH" > /dev/null 2>&1; then
70+
BRANCH="pr-$NUMBER"
71+
fi
72+
# The base is fetched apart from it: on pull_request_target the checkout
73+
# is the base branch itself, which git refuses to fetch into.
74+
git fetch -q origin "+refs/pull/$NUMBER/head:refs/heads/$BRANCH"
6775
git fetch -q origin "$BASE"
6876
git checkout -q -B "$BASE" "origin/$BASE"
77+
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
6978
7079
- name: Pre-flight and simulate
7180
id: sim
7281
shell: bash
7382
env:
7483
MODE: ${{ inputs.mode }}
75-
NUMBER: ${{ github.event.pull_request.number }}
84+
BRANCH: ${{ steps.fetch.outputs.branch }}
7685
BASE: ${{ github.event.pull_request.base.ref }}
7786
git_sim_auto_open: "false"
7887
run: |
7988
set -euo pipefail
8089
mkdir -p git-sim-out
8190
if [ "$MODE" = "rebase" ]; then
82-
git checkout -q "pr-$NUMBER"
91+
git checkout -q "$BRANCH"
8392
CMD=(rebase "$BASE")
8493
else
85-
CMD=(merge "pr-$NUMBER")
94+
CMD=(merge "$BRANCH")
8695
fi
8796
git-sim preflight --markdown "${CMD[@]}" > git-sim-out/report.md || true
8897
PAGE=$(git-sim -d --media-dir git-sim-out --output-only-path "${CMD[@]}" 2>/dev/null | tail -n 1 || true)

‎src/git_sim/preflight.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ def _analyze_merge(repo: git.Repo, args: List[str], report: PreflightReport) ->
757757
report.marks[c.hexsha] = "INCOMING"
758758

759759
# Deterministic conflict detection via git's own merge machinery (git >= 2.38).
760+
conflicts = False
760761
if not ff:
761762
mt = ["git", "merge-tree", "--write-tree", "--name-only", "--no-messages"]
762763
if unrelated_ok:
@@ -767,6 +768,7 @@ def _analyze_merge(repo: git.Repo, args: List[str], report: PreflightReport) ->
767768
else:
768769
# the merged tree's id, then one conflicted path per line
769770
conflicted = list(dict.fromkeys(line.strip() for line in out.splitlines()[1:] if line.strip()))
771+
conflicts = True
770772
report.escalate(Risk.CAUTION)
771773
report.warnings.append(
772774
f"Merge WILL conflict in {len(conflicted)} file(s): "
@@ -783,6 +785,15 @@ def _analyze_merge(repo: git.Repo, args: List[str], report: PreflightReport) ->
783785
report.recovery.append(
784786
f"A fast-forward only moves the branch: git reset --hard ORIG_HEAD puts it back on {_short_sha(head)}"
785787
)
788+
elif conflicts:
789+
# git stops at the conflict before committing, so there is no merge
790+
# commit to reset away yet
791+
report.recovery.append(
792+
"It stops at the conflict without making a merge commit: git merge --abort puts everything back"
793+
)
794+
report.recovery.append(
795+
f"Once you resolve and commit it, undo the merge with: git reset --hard ORIG_HEAD (back to {_short_sha(head)})"
796+
)
786797
else:
787798
report.recovery.append(
788799
f"Undo the merge commit with: git reset --hard ORIG_HEAD (back to {_short_sha(head)})"

‎tests/unit_tests/test_preflight.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ def test_merge_conflict_detected(repo):
9393
report = analyze("git merge feature", str(repo))
9494
assert any("conflict" in w.lower() for w in report.warnings)
9595
assert any("file1.txt" in w for w in report.warnings)
96+
# git stops at the conflict with no merge commit, so --abort comes first
97+
assert "git merge --abort" in report.recovery[0]
98+
assert "resolve and commit" in report.recovery[1] and "ORIG_HEAD" in report.recovery[1]
9699

97100

98101
def conflict_on_main(repo):

0 commit comments

Comments
 (0)