Reputation: 769
I somehow got my local repos (c9.io and my web server) out of sync and it's a huge mess. I tried to git pull, and then push changes and each time it screws up the other location.
What I'd like to do is get rid of all commits after e39a8ac, so I stop getting the behind 10 commits message. I tried doing a git rebase and revert and reset, but I don't know how to fix it.
PLEASE HELP. Git is good sometimes, but otherwise I feel lost.
Upvotes: 3
Views: 207
Reputation: 488103
You can try using force-push: git push -f origin master
. That may suffice. It may not. It may do too much. Be very careful with this.
It's often better, instead, to add new commits that undo the things you don't want done, and leave the previous commits in there, and then just push the new state. Git is great about adding new commits, and there's no danger like there is with force-push.
Remember that when using Git, you have your repository, and everyone else (such as c9.io
for one, and your web server for another perhaps) has their repository. You can do whatever you want to your repository. Getting them to do what you want to their repository is harder.
Your image shows that your master
is pointing to e39a8ac
, which is what you say you want. So your repository is OK now. Note that we refer to this as "master
points to e39a8ac
".
You have, in your repository, a short name origin
that abbreviates a URL. At that URL, there is another Git with another repository. You can run git fetch origin
to have your Git connect to their Git and obtain new-to-you commits from them. If and when you do this, your Git will record, in your repository, their master
as your origin/master
. This is how your Git remembers for you what it last saw over there. It looks like you did that, or something equivalent to that, at some point.
(So far this is all just setting things up so that you can see what I'm talking about below.)
You can also run git push origin <hash-or-branch-name>:<their-branch>
to have your Git connect to their Git send them any new-to-them commits. (Any commits they already have, you don't have to send.) Your Git then asks their Git, politely, if it would mind please setting its branch name to the commit-hash you have your Git suggest to them. They can refuse for any reason, but if they're cooperating with you, they are likely to refuse only for one reason: that your request would cause them to lose some commit(s).
Hence, you can run:
git push origin master:master
(which you can abbreviate as just git push origin master
1) to ask them to please set their master
to e39a8ac
. The problem is that they will notice that this would lose at least five commits—the five we can see in your image—and almost certainly another 5 (your own Git says that you are "ten behind" them, based on your Git's memory of their Git's master
).
Git is very, very much oriented to this concept of "adding new commits". It's always happy to assimilate new distinctive technology into its Borg Collective. But it tends to balk at the idea of taking stuff away.
Still, you can try using a "force push":
git push --force origin master:master
This changes your Git's polite request, please update your master
to e39a8ac
, into a command: Update your master
to e39a8ac
! Whether they will obey is another question entirely; it's up to them and their Git and their settings. If they do obey, that will erase some commits from their repository. That might be just what you want, and if it is, you may be done here.
But remember, there may be many repositories. Suppose they take your command, and now your Git has your master pointing to e39a8ac
and their Git has their master
pointing to e39a8ac
(so that your origin/master
also points to e39a8ac
). But then a third Git comes along and says to them: Hey, I have 4a3c63d
and nine more commits you could add to your master
, would you like them? Git being so Borg-like, their Git may immediately snarf them up and put them back into their repository ... and now if you connect your Git to their Git, you'll get those same commits back.
For the force-push to "take", you must convince every Git user that has a copy of the repository to set their master
back, so that they all throw out the ten commits you will be throwing out. If there are just the two repositories, you're good. If there's a third one but you convince them to do this too, you're good. Otherwise, consider an alternative: instead of trying to remove commits you don't like, just add yet another new commit that sets things back the way you do like them:
* 4a3c63d (origin/master) Merge ...
|\
| * dcca8ec made ONE CHANGE to console log
* | aa6b21e changed console log
* | ...
Suppose you added one new commit, let's just call it nnnnnnn
,2 that puts every file back the way you want it:
* nnnnnnn (master) Put everything back the right way
* 4a3c63d (origin/master) Merge ...
|\
| * dcca8ec made ONE CHANGE to console log
* | aa6b21e changed console log
* | ...
If you now run git push origin master
, your Git will offer their Git this new commit. They will greedily gobble it up and add it to their collective, and set their master
to nnnnnnn
too. And now you and they will match up, and any third Git that connects to them will pick up nnnnnnn
, and so on.
The drawback is that this leaves some useless commits behind, with their versions of all those files. But generally that's not terribly harmful (unless those files have secret passwords in them, or are multi-gigabyte movie or DVD images, or whatever).
1If you leave out the :master
, the default is that your Git asks them to set the same name you give: git push origin master
=> git push origin master:master
; git push origin xyz
=> git push origin xyz:xyz
; and so on. You can even specify more than one thing at a time: git push origin master xyz:hello
means git push origin master:master xyz:hello
.
2It's too hard to predict the next commit's hash ID. Even Git doesn't know yet, because one of the inputs Git uses to make it is the exact time at which you make it. Every second sooner or later changes the ID completely, even if everything else about the commit is exactly the same.
Upvotes: 4