I'm working on a feature branch, let's say
git checkout -b "Cool_Feature_1"
. I created 4 commits with atomic changes because it's easier to review them and they are all grouped, like "move file structure" or "remove some duplicated code".
Let's say in 1 of the 4 commits I moved a file.
After the work was done I pushed all the changes and created a merge request. Reviewer tells me to change the file path in commit 1, others look good.
How do I do that?
My approach:
git log
to find out the necessary commit
Then git checkout 7c802ef576fbad061c6fefb350fde386e7d09087
Make my changes again
git add .
git commit --amend
But now, if I do git push
I receive:
git push
✔ 10137 18:59:06
fatal: invalid refspec '(HEAD detached from 7c802ef57)'
In the end I want to do
git push -f origin Cool_Feature_1
and have that small change only be overridden in that 1 commit. Basically, I want to alter 1 commit from an already existing merge request.
The guys here suggest creating a new branch, but that is not an option for me.
CodePudding user response:
if you edits are easy to make, and you want to start over, you can go like this:
git checkout Cool_Feature_1
git reset --hard origin/Cool_Feature_1
now you have a local branch that is just like the one on gitlab
git rebase -i HEAD^^^^^
will start an interactive rebase
you'll be given a list of your recent commits. If you don't set your default to editor to something else, it will be vim
, which is hard to use if you don't know how.
Then each commit will have a pick
before it. Change pick
to e
for the commit you want to edit. Then save the file and exit the editor. It will then stop right after your commit. You can amend it like you said... and then type git rebase --continue
. Than you should
have something just like what is on origin except with that one commit changes. To make sure, go like this:
git diff origin/Cool_Feature_1
Also, I like using gitk
gitk Cool_Feature_1 origin/Cool_Feature_1
will show you the two histories side by side and where they diverge.
Then if you are happy with your local version of the branch, force push it to origin as you did in the question.
or do what you did:
git checkout 7c802ef576fbad061c6fefb350fde386e7d09087
but now you are on a "detched head" - but that's OK.
make your change
then you need to get all the commits that came after the one you checked out. You can cherry pick each one from the original branch:
git cherry-pick origin/Cool_Feature_1^^
git cherry-pick origin/Cool_Feature_1^
git cherry-pick origin/Cool_Feature_1
^
means one before. so what I put above is the 3 last commits. So do that if you were editing the 4th last. If you were editing the third last, then just:
git cherry-pick origin/Cool_Feature_1^
git cherry-pick origin/Cool_Feature_1
then see if you did it right like this:
git diff origin/Cool_Feature_1
Also, I like using gitk
gitk HEAD origin/Cool_Feature_1
the local branch is just called HEAD
this time because of how you checked out that commit.
Actually, it is really helpful to open gitk like that and leave it open for the whole process and look at it after each step.
If you are happy that your local branch is the same as your remote branch, except with that one commit changes, then force push it.
Since you don't have a local branch in this case, go like this:
git push origin HEAD:Cool_Feature_1 -f