简体   繁体   中英

How to "force" a pull request from a specific commit?

The scenario is the following:

  • We have around 10 commits that we want to revert from our master branch. They are causing some sort of issue and I need to revert to a specific commit 123abc ;

Some things we tried here:

  • We created a new branch called feature/something in order to revert the commit and do a pull request to the master branch. However, VSTS is complainng that we don't have new changes.

  • When we do git reset --hard 123abc into master branch, my local space is reverted to the given commit, that's OK so far. However, I don't have permission to force a push to the master branch.

So, my questions are:

  • Regarding the 1st attempt, how to make git understand that I want to pull those changes to master branch and don't complain?

  • Regarding the 2nd attempt, how to force a pull request from master branch from that given commit?

Thank you all!

There is no way to make a branch to an old commit through pull request.

If you have not force push permission, you should revert changes on a new branch and create PR to merge the new branch into master , or you can ask the team project administrator to reset master branch to an old commit.

Option 1: revert the changes on master branch

Assume the commit history on master branch as below, and the commits C1 to C10 are the commits you want to revert:

…---A---C1---C2---…---C10   master
  • If master branch has no branch policies, you can directly revert on master branch and push to remote.

     # On local master branch git revert C1^.. git push origin master

    After revert the changes, the commit history on master branch should be:

     …---A---C1---C2---…---C10---C10'---C9'---…---C1' master
  • If master branch has branch policies, you can create a new branch (such as feature/something branch) from master branch, then revert commits on feature/something branch and create a PR to merge feature/something branch into master :

     # On local master branch git checkout -b feature/something git revert C1^.. git push -u origin feature/something

    Then the commit history will be:

     …---A---C1---C2---…---C10 master \\ C10'---C9'---…---C1' fearure/something

    You can create a PR to merge feature/something into master . And it shouldn't complain there hasn't new changes unless you revert/merge on the opposite way.

Option 2: ask team project administrator to reset and force push to master branch

If there has no branch policies on master branch, you can ask team project administrator to reset master branch and then force push (as the 2nd attempt you tried). Or you can ask the administrator to allow you to force push.

Option 1: revert

In the first attempt, it seems you want to add a commit to master to undo the changes from the 10 commits. You're envisioning this as a merge between the current ip of master , and a commit before the 10 commits you want to undo.

Of course if this did what you're currently wanting, then that would mean that normal merges would be constantly undoing changes from one side of the merge or other - which is exactly what a merge is supposed to not do.

In git, the word for what you're trying to do is revert . If you have

x -- x -- x -- A -- B -- ... -- I -- J -- o <--(master)

and you want to undo A thru J , you could say something like

git revert -n A^..J

(replacing A and J with ID's or other expressions that resolve to the corresponding commits; in this example one way to spell it out would be

git revert -n master~11..master^

remembering that the first expression would point to A 's parent rather than A itself).

This will update your index and working tree to undo the changes from the specified range of commits. So then

git commit -m "Revert commits A through J"

If you don't want to have to explicitly commit, you can leave off the -n option, but then you'll get 10 new commits (one to undo each of the original commits).

The commits don't necessarily have to be sequential; you could name each commit individually instead of specifying a range. And this should work regardless of the branch topology. Do note that revert operations can conflict, and the more changes have occurred after a commit that you're reverting the more likely a conflict becomes.

As a special case, if the 10 commits make up all of a feature branch, as in

x -- x -- x -- x -- x -- x -- y --- M -- o <--(master)
           \                       /
            A -- B -- ... -- I -- J <--(feature_branch)

you could say

git revert -m1 M

(where M is again some expression like the commit ID of M , or master^ in this example, etc.)

This means you want to apply the inverse of the changes M made over its 1st parent ( y ). Be aware, though, that once you revert a merge you can't just redo the merge later (because from git's point of view, those changes are already merged in even though you happen to have later undone them). You could later "revert the revert", or you could do a rebase to recreate the branch with new commits and re-merge from that.

Option 2: rewrite history

On the other hand, you could remove the original commits from the history of the master branch. Your second attempt is one way to do that. As you note, not every remote gives you the permission to do a force push - and for good reason (there are side effects). Every method of rewriting history will ultimately require a force push, so if you don't have permission then this simply isn't an option.

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