No.
First of all, when you say "amend, commit (and force push)", are you referring to the git commit --amend
command? The naming of the amend
option can be a little confusing. While it does reflect the command's purpose, it suggests that it edits the existing commit - which it does not do, because that is impossible.
What you have after resetting is something like this
O <--(master)
\
A -- B <--(origin/master)
So you committed twice (A
and B
), but A
contains files you don't want in the repo, so you reset back 2 commits (to before A
). Then the first thing to understand is, if you do a commit --amend
from here it will be amending commit O
- not commit A
.
But also, what does it mean to "amend" a commit, given that - as I said above - you cannot change an existing commit? Well, it means you create a new commit - which has a new ID - and "replace" the old commit with it. Which sounds like hair-splitting, but it's important because "replacing" a commit doesn't do all the things you might assume it would do.
Let's suppose you reset to commit A
. In your example as described, that would be git reset --hard master^
(1 commit before the branch tip - so you've checked out the commit that was "wrong"). Now you have
O -- A <--(master)
\
B <--(origin/master)
Now you can edit the worktree (i.e. delete the unwanted files), and then you could tell git to "amend" commit A
. But what you'd get is
O -- A -- B <--(origin/master)
\
C <--(master)
C
is a new commit with a new ID. IF you only made small changes before the commit --amend
, then it applies mostly the same changes, relative to O
, as A
- but it is still an entirely distinct commit. In your local branch's history, C
replaces A
- but only in your local branch - not throughout the repository. B
still sees A
as its parent, and origin/master
still points to B
.
If you then force push, you will move origin/master
to C
. This is a history edit, which has consequences if the repository is shared with others. See the git rebase
docs under "recovering from upstream rebase"; this section is applicable to any rewrite, whether or not it involves the rebase
command. Also note that if you don't properly coordinate a force push with the other users of the repo, it is possible that any one of them will do the wrong thing when recovering and undo the changes you made.
So in addition to replacing A
with C
, this procedure removes B
from the branch history, because "replacing' A
with C
is not an in-place replacement throughout the repository.
You could fix that by rebasing B
from A
to C
. There are a few ways to go about that, such as
git checkout origin/master
git rebase --onto master HEAD^
This gives you
O -- A -- B <--(origin/master)
\
C -- B' <--(master)
Here I've used a notation that indicates that the new commit (B'
) applies the same changes as the old commit (B
) relative to a new base - but it is still an entirely new commit. Again this is a history rewrite, and you would have to coordinate with any other users and force push.
Depending on why those files should be excluded from the repo, it may also be important to know that this does not (yet) physically remove the original history (including the files you've deleted). Your local repo will hold onto them for at least as long as the old history remains in the reflog. There are steps you can take to perform an earlier clean-up locally; but the remote (depending on how it's hosted) might or might not have convenient procedures for removing the files from there. And nothing you can do would guarantee that the files are removed from any other clones that might exist.
So if the files contained sensitive information (and if anyone else had access to the remote), you will need to treat that information as compromised. If the files are simply large, you can search for existing questions and answers that detail how to purge them from history to recover the space