gitgithubpull-requestgit-fork

How can I clean up my GitHub fork's commits and branch to make clean PRs in the future?


My issue in short:

I was contributing to a repo on GitHub, so I forked, and I created a new branch, made my additions, and submitted a successful PR back to the origin repo (#18 in it). The result now is that I now fear I have muddied my fork's history such that I can't neatly contribute any more with it.

I am seeking a solution that will not muddy the origin repo's commit history for any future pull requests I make from this fork.

Steps and graphs of my process:

My feature branch was named added-pods. I was then going to submit a pull request of my changes to be accepted to the original repo on GitHub.

What it looked like before pull request:

main     --A
            \
added-pods   B--C--D--E

What I expected pull request on origin to do to my fork:

main     --A------------F-
            \          /
added-pods   B--C--D--E

Origin:

main     --A--B--C--D--E--F     (or  A-----F)

What it actually looked like after pull request and syncing:

My fork:

main     --A------------F
            \          
added-pods   B--C--D--E

Origin:

main     --A------------F

There was no difference in the code between my feature branch and main now. Yet, my feature branch wasn't visually merged, locally or on GitHub. It appears as if a 'magical' commit (F) showed up in my fork's main branch and that my feature branch was never merged. This was different than what I saw other contributor's PRs into the origin repo (from the origin repo's graph perspective). I couldn't see how what I did was different from theirs. I tried fixing by PR-ing my fork's feature branch into my fork's main branch. After a PR inside my fork, it looks like this:

main     --A------------F---G
            \              /
added-pods   B--C--D--E---/

Now I have a PR commit G. And in the commit history on GitHub, the difference between F and G is nothing, so it looks like a pointless and confusing commit. I may have a fundamental misunderstanding about pull-requests. I thought merges, including PRs, bring commits from a branch onto the targeted branch's commit history. The PR commit F did not seem to do that.

From searching SO questions, PRs can't be undone, only 'reverted', which I read would only add another commit in the GitHub history, G won't disappear. I believe I want to remove G but get a connecting line, because G literally adds confusion to me.

Summary question: Where do I reset to, or branch from, so I avoid muddying the history of the upstream or origin repository when pull-requesting in the future? In other words, keeping it clean and no 'useless' commits?

I have also considered this other question but because PRs can't be undone I think those options won't work because of my PR inside my own fork. I can locally reset to F with git reset HEAD^ suggested from this SO answer but that didn't fix my "unmerged branch" problem.


Solution

  • I solved it by doing a bit of rewriting the history on the main branch using a new commit. Most of this was helped out by this SO question and answer about detached HEADs that I found. Note you should not rewrite history in public repos unless you know it won't affect anyone. Because my fork was small, it was only 1 commit, and I know of no other forks that came from mine, I was confident this is a safe move.

    1. I went back one commit on the main branch. This made my local HEAD point to the squash commit that was synced from the origin (or upstream) repo, not my fork's pull request merge.
    git reset --merge fb750f2
    # (the hash fb750f2 is the hash of that squash commit, behind my undesired merge)
    

    From what I know, git reset HEAD^ would do the same here as using the --merge flag if your working directory was clean, which mine was. And HEAD^ refers to the first parent of the merge commit.

    1. I made one new (simple) commit, which was just fixing a little problem in one of the files. I intended to make this change anyway for my next PR contribution.
    # ... changed file ...
    git add .
    git commit -m "...message here..."
    

    Now, I had a detached HEAD.

    1. I fixed the detached HEAD by performing the steps recommended in the SO answer linked above to rewrite main over to my new commit.
    git branch -f main
    # at this point, head is still detached and a regular push is rejected.
    git checkout main
    # now the history is changed! A force push is still required.
    

    Locally, that undesired merge is finally off of main.

    1. I force pushed these changes to my fork, rewriting the public main history:
    git push --force
    

    Finally, GitHub reports (as expected) my main branch is now 1 commit ahead of the origin, and that commit is my small new one I created which I welcome gladly.

    Regarding my initial utmost concerns:
    I believe this will cause no longer pose issues with future branches/PRs to the origin repo, because now the only diff between my fork's main versus the origin main is my one new commit (which fixes a little problem I intended to incorporate in a future PR anyway.)
    As for the line connecting the branches adding-pods and main which I sought, I have decided to let go of that. It is not a necessity I see.