Reputation: 8889
My current git log is
I want to discard Including OpenCV
and delete the same (as it contains so much unwanted library data), I simply want to keep what I have right now and push it.
What I tried when the push got rejected:
1) Rebase resulted in
2) Merge resulted in
What I want:
Upvotes: 0
Views: 37
Reputation: 45659
Update based on comments
Original Reply
Ok, so the remote has
A -- B -- C <--(master)
Locally you see this as
A -- B -- C <--(origin/master)
but also you have your own commit based on B
A -- B -- C <--(origin/master)
\
D <--(master)
Now to discard C
means you want to remove C
from the history of origin/master
; this is a history rewrite affecting a commit that has been shared via the remote repo, so you would need to coordinate with all other users of the repo to do this safely. (If you try to do it without such coordination, one likely outcome is that someone else will end up undoing whatever you do.)
From a purely mechanical point of view, if you say
git push -f origin master
(and if you have sufficient access rights to do it) it will "move" origin/master
to master
, leaving C
"unreachable".
This does not remove C
from the repo. It's not true (as others suggest in comments) that it can't be undone - in fact if the repo has other users and you don't coordinate with them, it's likely to be accidentally undone. It does put every clone of origin
(with the exception of your own) in a broken state that will require recovery - see "recovering from upstream rebase" in the git rebase
documentation (because any remote history rewrite is equivalent to an upstream rebase in this regard).
While making C
unreachable is enough that you wouldn't see it unless you knew to look for it, if you want to actually delete C
there's quite a bit more involved - especially if you need it removed from the remote, and don't want to risk it "reappearing" (which means you need it removed from everyone else's local repo as well). Unless C
either takes up a huge amount of disk space or contains sensitive data, it may be better to keep it in the history and just use a new commit to undo the changes it applied (see git revert
).
Note that merging or rebasing, as you show in your two examples of "what doesn't work", do the opposite of what you might want; they bring the unwanted commit into your master
history. Still, you would do that if you take the advice to revert instead of rewriting history.
Update
With the clarification that the "bad" commit brings in a huge amount of data, it seems what's needed is a rewrite; but as noted above, simply rewriting the ref does not remove the commit from the repo.
That is, moving origin/master
to D
doesn't necessarily guarantee that C
never gets transferred during a clone
, fetch
, or pull
(though you wouldn't expect it to; it depends if the server tries to take a shortcut with existing pack files). And in any case it doesn't free up space within origin itself.
In a local repo, what you need to do is make C
unreachable and then get gc
to run. But getting C
truly unreachable means not just moving the origin/master
ref (and any other refs that could reach C
, potentially including some you'd have to know to look for), but also clearing any reflogs that point to C
.
Fortunately reflogs are temporary, local, and kind of a "useful when they're useful" thing; so it may be safe to just rm -rf .git/logs
and be done with the matter. But that will throw out all of your current reflogs, so if you want to be more selective see the git reflog
docs.
Then you can manually invoke gc
, like
git gc --aggressive --prune=now
and hopefully this will reclaim the space locally.
Getting gc
to run on the remote is another matter, and it depends on how the remote is hosted. Worst-case example: as of the last version I checked, TFS didn't offer a way to trigger gc
; so it might be easiest to just trash the remote and start over. But of course if you just host it on a shared drive (using ssh, or a web server, etc.) then you can clean it up just like a local repo.
Of course, each other local repo that's out there with a copy of the commit, until that repo is cleaned up, is one push away from putting the binary bloat right back in the remote.
Upvotes: 1