0

Alright - so I had a guy (in a school project - don't panic) commit a full eclipse workspace complete with .class files and .settings/ directories. What I did was to clone the repo and make a .gitignore file and issue :

$ git reset --soft HEAD^
$ ... unstaged all files and added .gitignore and all files that it filtered in ...

Then I tried :

 $ git commit -c d1cf2d8173234b444c601d5e294a5cf6d790fa2c

Where the SHA is the SHA of the online commit. It won't let me push :

Pushing to https://USERNAME@git.assembla.com/PROJECT.git To https://USERNAME@git.assembla.com/PROJECT.git ! [rejected]
master -> master (non-fast-forward) error: failed to push some refs to 'https://USERNAME@git.assembla.com/PROJECT.git' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.

My question is what should I have done instead ?

So how exactly should I go about deleting a commit in this scenario. Do not warn me that it shouldn't be done - in this case it is very well acceptable, recommended and necessary to edit the history (I want to reclaim the space in the online repo). Also - I am not really worried how to force the push - I want the easier/cleaner way of replacing the remote HEAD commit with another.

It all starts with a clone...

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • possible duplicate of [How do I push amended commit to the remote git repo?](http://stackoverflow.com/questions/253055/how-do-i-push-amended-commit-to-the-remote-git-repo) – CB Bailey Apr 29 '12 at 12:47
  • @CharlesBailey : not really a dup - I am not interested in amending - I just want to _completely replace_ the commit with a small part of the commited files + a .gitignore. Force does not work for some reason - which is the suggested route in question cited. Also I used `git commit -c ` which is probably not the thing to do ? – Mr_and_Mrs_D Apr 29 '12 at 13:26
  • It doesn't really whether you amend or wind back the branch and make a new commit, the fact is that you are trying to push a commit that is not a direct descendant of the remote branch. The problem that you facing is exactly the same as the problem in the question that I linked to. – CB Bailey Apr 29 '12 at 13:33
  • @CharlesBailey: Yes I saw this - I could edit the question - what I really want to know is how I make the repo _forget_ about the fluffy commit and instead replace it with my commit. In short clone _then what ?_ The question linked is full of _don't do it_ and instructions of how to ammend your stupid messing up of history - and your answer details how to --force - but there is no clear account on how to actually do it -_saving the space in the repo_. Thanks for your patience – Mr_and_Mrs_D Apr 29 '12 at 13:37
  • @CharlesBailey : please see the edited answer - and do unvote the close - the question linked is how one should push an amend - my question is how should one amend (without much fuss in pushing or otherwise) – Mr_and_Mrs_D Apr 29 '12 at 14:00
  • see http://meta.stackexchange.com/questions/915/can-we-have-the-ability-to-rescind-a-close-vote-before-it-closes. – CB Bailey Apr 29 '12 at 14:05
  • @CharlesBailey : well ok - how about an answer then before this is closed :D – Mr_and_Mrs_D Apr 29 '12 at 14:06
  • You won't get the space back until you purge all references to the unwanted commit(s) and force a garbage-collect. This applies to all of the repos that contain the bad commit(s) (yours, your remote, any other clones of that remote). In any case, no matter how you do it (with one commit as above, or with `git filter-branch` or `git rebase` etc) you'll need to get the remote repo to give you permission to push the non-fast-forward change. Or, log in on the remote machine and do it there. – torek Apr 29 '12 at 21:58

2 Answers2

1

You could use the --force flag in your push statement, but it is risky if others are using the same repo. Otherwise, you may want to update back to the remote head and use a Git revert.

Scott Harwell
  • 7,457
  • 2
  • 28
  • 41
  • Thanks a lot - no it's 2 people using it - and it's a pet project - so no harm done. I read that one should merge etc etc but I want to get rid of all the fluff uploaded - the repo has space limitations. Can you elaborate on the _update beck to the remote head and use a Git revert_ ? – Mr_and_Mrs_D Apr 29 '12 at 12:54
  • Failed !: `$ git push -f Password for 'https://USER@git.assembla.com': Counting objects: 102, done. Delta compression using up to 8 threads. Compressing objects: 100% (60/60), done. Writing objects: 100% (101/101), 1.65 MiB | 28 KiB/s, done. Total 101 (delta 8), reused 64 (delta 5) remote: error: denying non-fast-forward refs/heads/master (you should pull first) To https://USER@git.assembla.com/REPO.git ! [remote rejected] master -> master (non-fast-forward) error: failed to push some refs to 'https://USER@git.assembla.com/REPO.git'` – Mr_and_Mrs_D Apr 29 '12 at 13:04
  • try `git push --force remote branch` – Scott Harwell Apr 29 '12 at 13:09
  • `remote: error: denying non-fast-forward refs/heads/master (you should pull first) To https://regar@git.assembla.com/texlogismikou2012.git ! [remote rejected] master -> master (non-fast-forward) error: failed to push some refs to 'https://USER@git.assembla.com/REPO.git' fatal: Full write to remote helper failed: Invalid argument` -- maybe another approach ? reclone and ... – Mr_and_Mrs_D Apr 29 '12 at 13:14
  • That's weird that it's rejecting a force. There are a few ways to do this. You may want to Google git revert to see if that helps. Otherwise, yes, a new clone > commit changes > push will work. – Scott Harwell Apr 29 '12 at 13:25
  • A new clone and commit will certainly work but I want to make git to completely forget about all the binary crap in the repo. Can you elaborate on revert ? – Mr_and_Mrs_D Apr 29 '12 at 13:27
  • 1
    Presumably the remote has `receive.denyNonFastForwards` set in its config: "receive.denyNonFastForwards If set to true, git-receive-pack will deny a ref update which is not a fast-forward. Use this to prevent such an update via a push, even if that push is forced. This configuration variable is set when initializing a shared repository. " – torek Apr 29 '12 at 22:07
  • @torek:It does indeed - and it appears (assembla) that I have to go through the moderators to change this setting. Anyway my question is what is the best way to achieve what I want - push aside. – Mr_and_Mrs_D Apr 29 '12 at 22:25
1

Aside from having to get the remote repo admins to allow you to rewind the "master" branch, see http://help.github.com/remove-sensitive-data/ and in particular, the "cleanup and reclaiming space" section.

It's often simplest to start over with a new remote and have the remote-admins delete the old one entirely, in cases like yours. :-)

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks - but still my issue is how should I proceed _localy_ ? Clone then what ? Reset ? Amend ? – Mr_and_Mrs_D Apr 29 '12 at 23:42
  • Do whatever you find easiest. Since you only have one "bad" commit, `git commit --amend` will be pretty easy, and is probably how I would go, since you can repeat it as needed: `git rm -r this-definitely-goes and-that-too; git commit --amend -C HEAD; git show` ... oops, forgot one, repeat with missed part. – torek Apr 29 '12 at 23:50