From Nick Janetakis – Change a Git Commit in the Past with Amend and Rebase Interactive (https://nickjanetakis.com/blog/change-a-git-commit-in-the-past-with-amend-and-rebase-interactive)
# Figure out which commit you want to edit by getting its SHA. git log # Start an interactive rebase ($SHA = your commit's SHA and the ^ is important!). git rebase --interactive $SHA^ # [Change 'pick' to 'edit' for your commit and save the buffer] # [Add your changes with git add -p, etc.] # Change the commit and optionally add --no-edit if you want to keep the existing message. git commit --amend # Finalize and apply the rebase. git rebase --continue # Or cancel the rebase and go back to what it was like before you started rebasing. git rebase --abort
I recently wanted to merge a pull request in a git repository, where a lot had changed in master since the pull request was opened. The owner of the repository wanted me to do a
rebase instead of
merge, so I this is what I figured out:
Step 1) Update your branches.
Update all branches from the remote repository to make sure everything is up to date (
newfeature is your branch with the pull request,
develop is the branch it should be merged to):
$ git checkout develop $ git pull $ git checkout newfeature $ git pull
Step 2) Perform the rebase:
git rebase develop ... CONFLICT (content): Merge conflict in <bla> error: Failed to merge in the changes. Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort".
After each time git stops with an error, resolve the conflicts and use
git add. Do not commit anything during the rebase. Instead, just continue the rebase until everything is fine.
git rebase --continue
Now, you will have some modified files. You can make some final changes if necessary, and then commit your changes:
git add <bla> <blubb> git commit -m "Resolve conflicts from rebase"
Step 3) Push your changes to the remote repository.
Unfortunately, using only
git push will not work, but give the message “Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: ‘git pull …’) before pushing again.”
Do NOT use
git pull at this moment!!
Instead, force push your changes onto the remote repository:
git push --force-with-lease
Now, you have overwritten the history on the remote repository with your local history. That is fine. Now you can merge the pull request and delete the branch and go on your merry way.
Step 4) BUT…
If you are not yet at the place where you merge the pull request, but someone else wants to work with the branch, that person is in trouble! A normal
git pull on the branch will fail, because history was changed! What you need to do is:
git pull --rebase
Situation: You create a branch
develop at point X to develop your super cool new feature. You do some commits in your branch. Meanwhile there have been some changes in
develop that you want to have in your new branch. To do this, rebase your branch. Basically, this replays every commit in your branch on top of the current state in the branch you do the rebase against. Do a rebase as follows:
$ git checkout develop Switched to branch 'develop' $ git pull ... $ git checkout newfeature Switched to branch 'newfeature' $ git rebase develop First, rewinding head to replay your work on top of it... Applying: intermediate commit
Before doing this, you need to commit or stash all your changes. During the rebase, if there are conflicts, you need to resolve them one by one for every commit in your branch. You can simplify conflict resolution in one of two ways: use the flag
-Xours to always take the version in the branch that you are rebasing against (
develop in our example); or use the flag
-Xtheirs to always take the version in your branch.
When there are conflicts, you need to resolve them. To resolve a conflict, edit the file that has the conflict and remove all places indicated by
add all the modifications to the staging area. You can commit, but you do not have to. For things that you know they will be resolved later on anyway, you can also chose
git rebase --skip to ignore the problem (e.g., if a file was deleted in your branch and edited in the other and you know you copied the new file into your branch in a later commit). At the end, there may be things you need to commit to finalize the merge, then the rebase is complete. Don’t forget to push the result to your remote branch!