开发者

moving commits to new branch, removing from current branch on pushed repo

I'm the manager of several git repositories for a team and frequently have this problem. Another team member accidentally commits their work on a master or staging branch, when they should have created a feature branch instead.

Those commits aren't ready to be pushed live so I'm stuck. I know how to reset the current branch after making a new branch but that doesn't work properly when things have all been pushed through the remote repo.

I need to a way to move the last x nu开发者_StackOverflow社区mber commits from branch A to new branch B, remove those commits from branch A (in a way that allows me to push safely back to the remote repo). When branch B is complete, I need to be able to merge it back to branch A.

I've found a ton of suggestions, but none work properly with already-pushed commits.


As I understand the situation, someone has pushed commits to master in your central repository (origin) that you don't want there, and you want to (a) fix this on your local repository and then (b) push the fixed branches back to the central repository. adymitruk's answer tells you how to force push the master branch - part (b) - but it's worth saying a little about (a) as well. The final, and most awkward, consideration is (c): how the other people who are using the repository will deal with the rewritten master branch.

Firstly, I think it's worth considering whether it would be OK to just revert the commits that shouldn't be on master. This option will cause the least disruption to the other people who have already pulled from master and give you less work in explaining to people how do deal with the result - part (c). However, if you've decided that you mustn't have those commits followed by reverts in the master branch then here are the steps you should take:

(a) Fixing master locally

This bit is pretty easy. As usual with git, make sure that git status is clean. Then:

# Make sure you're on master:
git checkout master

# Create a branch at this point for the commits that your co-worker should
# have put on a topic branch:
git branch ill-advised-experiment

# Reset your master branch to the last good commit:
git reset --hard <SHA1-OF-LAST-GOOD-COMMIT>

(b) Pushing the revised master and topic branch

Your master now doesn't contain the complete history that's in origin's master, so you have to "force push":

git push -f origin master

... but you can push the new topic branch as usual, of course:

git push origin ill-advised-experiment

(c) Letting other people know what they should do

The risk after you've force-pushed a rewritten master branch is that someone has already done a git pull or git pull --rebase, so they have the accidental commits in their master branch. If that person then pushes to master on origin, the bad commits will be back in the master branch and you're back to square one. So, supposing the earliest bad commit has the object name (SHA1sum) f414f3l, you can ask people to check:

git branch -a --contains f414f3l

If they get an error, then that commit isn't in their repository at all, and it's all fine.

If they see that only the origin/master remote-tracking branch contains that commit, again it's all easy - they should just run git fetch origin to update their remote-tracking branch.

However, if both master and origin/master contain that commit, the user needs to be a little more careful. Firstly, the user should stash or commit all their work, to make sure that git status is clean. Then I would suggest the following:

# Leave a branch pointing to your old master, just to make it easy to find
# commits from there:
git checkout master
git branch old-master

# Now update all the remote-tracking branches from origin (you should see
# a "forced update" message for master):
git fetch origin

# Now reset the master branch to the right remote version:
git reset --hard origin/master

Now, if this user only had a few unstaged and uncommitted changes, they can then just git stash apply and carry on.

If they'd just done one or two new commits, it's probably easiest to find the object names of those commits from git log old-master and do git cherry-pick <SHA1sum-OF-MY-COMMIT> for each one. Then they can carry on as normal.

Finally, if they'd done a lot of commits, it's probably easiest to use an interactive rebase to apply those commits onto the new master, and skipping the bad commits. That would involve:

# To be extra cautious, create a new branch based on "old-master" for
# rebasing and switch to that:
git checkout -b old-master-for-rebasing old-master

# Start an interactive rebase:
git rebase -i master

# At this stage, delete every line that refers to a bad commit or anything
# that shouldn't be in master now.  Leave everything else in the file, as
# a line beginning with "pick".

# If all went well, this branch can now be merged into master, which should
# be a fast-forward merge:
git checkout master
git merge old-master-for-rebasing

I hope that's of some use.


If you are in control of the team and communicate it to everyone, force the push after you get the repository looking like you want it to locally.

git push origin master -f

Because you already pushed it, there is no other way to do this other than reverting all the commits that make up that feature.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜