0

I'm currently working on a git branch based off of branch main with a HEAD of commit A. I realized I wanted to split the work I was doing into two PRs, but I want to preserve the history properly. An idea I had was to git reset --soft main, unstage the parts I want to separate out, and commit the remaining bits so HEAD is now one commit ahead of main on commit B.

Ideally, at this stage, I would like to git reset --hard A and make a commit on top of it that gets me to working state in commit B. However, I can't figure out a way to add a commit that is the diff between A and B.

Does anyone have an idea for how I can make this commit, essentially removing all of the stuff from my branch that I wanted to separate out?

Matt Hauff
  • 65
  • 7
  • I'm not sure I read your question correctly: is your goal to end up with the content of `A` ( the initial complete commit) on top ? or the content of `B` (the "partial" commit) ? – LeGEC Apr 15 '23 at 10:00

2 Answers2

2

I'd suggest using git rebase to solve this.

  1. Make a branch corresponding to commit A.

    git branch branch-A
    
  2. Switch to a branch B and commit your changes

    git checkout -b branch-B
    git add ...  # Add your changes
    git commit
    
  3. Rewrite branch B to not include branch A.

    git rebase -i main
    # When the text editor pops up, remove the commit from branch B which is already committed to branch B.
    # Leave the commit which is only on branch B.
    # Save your changes.
    
  4. You now have two branches, branch-A and branch-B, each of which only contain one commit.

Nick ODell
  • 15,465
  • 3
  • 32
  • 66
  • The problem here is that I want to preserve the `main` thru `A` history in `branch-B`. I want `branch-A` to remain as it was and `branch-B` to be `branch-A` +1 commit which brings me to the state in `commit B`. – Matt Hauff Apr 14 '23 at 20:03
  • @MattHauff If the two have commits in common which aren't present in main, doesn't that contradict your goal of separating the two PRs? – Nick ODell Apr 14 '23 at 20:06
  • I want `branch-A` to gain a commit that removes all of the now separate stuff. This is now a smaller, more reviewable PR. I would then like to make a new branch (`branch-B`) which reverses the operation (gains a commit that adds all of the previously removed stuff.) Once `branch-A` is merged to main and `branch-B` is pointed to main to merge, `branch-B` will look like only the stuff that was removed from `branch-A` and added back to `branch-B`. – Matt Hauff Apr 14 '23 at 20:25
  • 1
    @MattHauff That sounds like [this question](https://stackoverflow.com/questions/17324645/git-create-commit-from-diff-between-two-branches). – Nick ODell Apr 14 '23 at 20:28
  • Yes! Thanks! I forgot that `git reset` worked for commits not in the history of the current branch too. – Matt Hauff Apr 14 '23 at 21:03
0

If I understand correctly, you want to create a commit with the exact content of A on top of B.

This can be done in several ways, one of which is:

# from commit B:

# restore content of A:
git restore --staged --worktree --source A -- .
# or using shorthand:
git restore -SW -s A -- .

# commit:
git commit
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • I think I misunderstood your question, if you want to end up in state `B` on top of `A`, just switch `A` and `B` above – LeGEC Apr 15 '23 at 10:01