简体   繁体   中英

Excluding a commit from a PR that is already in a PR

I have an open PR with a commit I did

I made another commit and want to create another PR with just these changes.. however the previous commit is in there.

I realize branches would resolve this, yet, here we are. Do I just need to wait for the PR to be merged?

I have an open PR with a commit I did

At that point your repository looked something like this.

A - B [master]
     \
      C [pr1]

Commit B is where master is at. And you have a branch called pr1 with a commit C on it.

I made another commit and want to create another PR with just these changes.. however the previous commit is in there.

What probably happened is you branched from pr1 rather than master resulting in this.

A - B [master]
     \
      C [pr1]
       \
        D [pr2]

When you make a PR for pr2 by default the base branch is master so it shows C and D in the PR.


If the work in D does not depend on C what you want is for pr2 and commit D to be branched from master .

      D [pr2]
     /
A - B [master]
     \
      C [pr1]

You can fix this by rebasing pr2 onto master .

git rebase --onto master pr1 pr2

That says to replay the commits starting at (but not including) pr1 to (and including) pr2 onto master . Then you can push pr2 and create an independent PR.


If the work in D does depend on C then it's best to leave pr2 on top of pr1 . Create a PR for pr2 with the base being pr1 instead of master . Once pr1 is reviewed and accepted, then pr2 can be reviewed and accepted.

Be sure to make a note in the PR description that pr2 is stacked on top of pr1 so the reviewer doesn't miss it. "This depends on #123" where #123 is the ID of pr1 's PR.

Just create a new branch from whatever point you want to start and cherry-pick the other branch. That will apply the changes involved on the last revision of the other branch and no other changes (assuming it's the last revision from that branch).

An easy way to do this, is by using interactive rebase .

If you run git log --oneline on your branch, you should see something that looks like this:


ccccccc (HEAD -> your-branch-name) Your (good) commit you want to keep
bbbbbbb bbbbbbb Your (bad) commit you want to remove from history
aaaaaaa (master) Commit from you or someone else

当前

You say you want to remove bbbbbbb replacing it with ccccccc .

Because ccccccc contains changes since bbbbbbb , removing it would cause lots of conflicts, as you'd have to merge ccccccc into aaaaaaa .

The git way to do it, is to squash ccccccc into bbbbbbb , creating a new commit ddddddd . And for that, you'd do the following steps:

1 . Run git rebase -i aaaaaaa to open the interactive rebase, starting from the commit immediatelly before the one you want to remove

This will open your configured text editor with something that looks like this:


pick bbbbbbb Your (bad) commit you want to remove from history
pick ccccccc Your (good) commit you want to keep

# Rebase aaaaaaa..f5a9551 onto aaaaaaa (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
#   However, if you remove everything, the rebase will be aborted.
#
#   
# Note that empty commits are commented out

The list shows what the interactive rebase will do: From aaaaaaa , pick bbbbbbb , then pick ccccccc

2 . As I said above, you want to squash ccccccc into bbbbbbb , so replace the word pick before ccccccc by squash :


pick bbbbbbb Your (bad) commit you want to remove from history
squash ccccccc Your (good) commit you want to keep

3 . Save the file, and close the text editor.

4 . Another text editor will open, to ask you to specify the message of the new commit being created, with the combination of ccccccc and bbbbbbb - which I'm calling ddddddd for the sake of this example:


# This is a combination of 2 commits.
# This is the 1st commit message:

Your (bad) commit you want to remove from history

# This is the commit message #2:

Your (good) commit you want to keep

Here you probably want to delete everything except the last line, which has the message of your latest commit, but feel free to customize the message however you like.

5 . Save the file, and close the text editor.

The rebase is done, and your history should look like this:


ddddddd (HEAD -> your-branch-name) Your (good) commit you want to keep
aaaaaaa (master) Commit from you or someone else

在推之前

6 . Now, all you have to do is to send to push the branch back to your origin (eg GitHub/BitBucket/GitLab), etc. in order to update your pull-request.

For that, you'll have to do a push --force , so that your remote branch is replaced by this new one.


git push origin your-branch-name --force

最后结果

Of course, you always have the option of closing the previous pull-request and opening a new one instead (with a different branch name).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM