To receive the new commits
git fetch
Reset
You can reset the commit for a local branch using git reset.
To change the commit of a local branch:
git reset origin/main --hard
Be careful though, as the documentation puts it:
Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.
If you want to actually keep whatever changes you've got locally - do a --soft reset instead. Which will update the commit history for the branch, but not change any files in the working directory (and you can then commit them).
Rebase
You can replay your local commits on top of any other commit/branch using git rebase:
git rebase -i origin/main
This will invoke rebase in interactive mode where you can choose how to apply each individual commit that isn't in the history you are rebasing on top of.
If the commits you removed (with git push -f) have already been pulled into the local history, they will be listed as commits that will be reapplied - they would need to be deleted as part of the rebase or they will simply be re-included into the history for the branch - and reappear in the remote history on the next push.
Use the help git command --help for more details and examples on any of the above (or other) commands.
To receive the new commits
git fetch
Reset
You can reset the commit for a local branch using git reset.
To change the commit of a local branch:
git reset origin/main --hard
Be careful though, as the documentation puts it:
Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.
If you want to actually keep whatever changes you've got locally - do a --soft reset instead. Which will update the commit history for the branch, but not change any files in the working directory (and you can then commit them).
Rebase
You can replay your local commits on top of any other commit/branch using git rebase:
git rebase -i origin/main
This will invoke rebase in interactive mode where you can choose how to apply each individual commit that isn't in the history you are rebasing on top of.
If the commits you removed (with git push -f) have already been pulled into the local history, they will be listed as commits that will be reapplied - they would need to be deleted as part of the rebase or they will simply be re-included into the history for the branch - and reappear in the remote history on the next push.
Use the help git command --help for more details and examples on any of the above (or other) commands.
Pull with rebase
A regular pull is fetch + merge, but what you want is fetch + rebase. This is an option with the pull command:
git pull --rebase
In your particular case, commits have been removed which you don't want to be reapplied. This has to be done manually. Therefore, the rebase needs to be interactive so these commits can be skipped:
git pull --rebase=interactive
or as of Git 2.26 can be shortened to:
git pull --rebase=i
Am I using git push --force the right way?
How to pull after a forced git push? - Stack Overflow
Can you do pull (or equivalent) from a branch when history is rewritten without merge?
Git - After Rebase, recommend Push (Force)
Hello everyone,
I would like to know if I'm using git push --force the right way. Here is my scenario:
-
I branched off master (let's call my branch dev1) which I did some work on and then pushed up remotely
-
A ton of work has been done on `master` I've been working on dev1 locally
-
I want my local dev1 branch to have all the updated changes that master has so I rebased
-
At this point, my local dev1 is way out of sync with remote dev1. Git is saying if I want to sync them up then I need to do a git pull (but I definitely don't want to pull the changes down from the remote branch to my newer, local branch).
Assuming no one else works on dev1, am I supposed to git push --force to sync local `dev1` to remote `dev1`? If not, what are my alternatives?
Throwing away your local changes
If you want to discard your work, fetch and reset. For example, if you have a remote named origin and a branch named master:
$ git fetch origin
$ git reset --hard origin/master # Destroys your work
Keeping your local changes
If you don't want to throw away your work, you will have to do a git rebase --onto. Suppose the old origin looks like this:
A ---> B ---> C
^
origin/master
And you have this:
A ---> B ---> C ---> X ---> Y ---> Z
^ ^
| master
origin/master
Now, the upstream changes change things:
A ---> B ---> C ---> X ---> Y ---> Z
\ ^
---> B'---> C' master
^
origin/master
You would have to run git rebase --onto origin/master <C> master, where <C> is the SHA-1 of the old origin/master branch before upstream changes. This gives you this:
A ---> B ---> C ---> X ---> Y ---> Z
\
---> B'---> C'---> X'---> Y'---> Z'
^ ^
| master
origin/master
Notice how B, C, X, Y, and Z are now "unreachable". They will eventually be removed from your repository by Git. In the meantime (90 days), Git will keep a copy in the reflog in case it turns out you made a mistake.
Fixing mistakes
If you git reset or git rebase wrong and accidentally lose some local changes, you can find the changes in the reflog.
In the comments, a user is suggesting git reflog expire with --expire=now but DO NOT RUN THIS COMMAND because this will DESTROY your safety net. The whole purpose of having a reflog is so that Git will sometimes save your neck when you run the wrong command.
Basically, what this command will do is immediately destroy the B, C, X, Y, and Z commits in the examples above so you can't get them back. There's no real benefit to running this command, except it might save a little bit of disk space, but Git will already purge the data after 90 days so this benefit is short-lived.
If you do not have local commits, this will recover your checkout from a force push. You will be up to date with the remote branch, and able commit your local work after that.
git fetch
git stash
git reset --hard origin/master # destroys your work
git stash pop # restores your work as local changes
git mergetool # fix any conflicts
At this point you have your local changes as they were before. Your checkout is up to date with all the changes on master, or whatever branch you are working from.
I have this situation.
Somoene create a branch that I checkout locally (or create PR and use use github command to checkout the PR).
The author of the branch modify the history (do a rebase or squash).
The branch can only be midified bu the author (a social rule), so I want to fetch the new changes and have the same history as the author.
Is there something like git pull --force? Or is the delete a branch and checkout it again the only option?
What is the simplest way to achieve something like this?