About a week ago, I was pushing my .gitignore file to my repository and was running into small issues with that, and finally figured it out, but noticed that all my storyboards were in the repository too. In a stroke of genius, I looked into getting them out of there and found out about the above git reset command and just put that into my terminal and patted myself on the back and life went on. I just realized today after installing some cocoapods that all my storyboards I spent weeks working on are gone and put two and two together. I've spent the last hour reading through the similar questions, but haven't found anything after reading for a while and am wondering if any other xcode users have run into the same issue and can help.
I should also add that I had only added the storyboards to the stage and hadn't committed them yet at the time of the reset, so today I was using the git reflog command in hopes that they were in the lost and found. I had read that the garbage collection doesn't happen for a month so I don't think (I hope) they're just gone
I downloaded the AWS SDK today and that's all the git reflog command seems to be showing at the moment. Do I need to roll back the git rest HEAD{} command further?
Thank you very much!
You note in a comment that you did a git stash
This is a crucial bit of information, which changes everything. Fortunately, it also makes recovering much easier. In particular it means that your missing files are not "dangling blobs" and do have their original names saved. (Note, by the way, that git stash means git stash save; I'll use the longer form below to distinguish it from other git stash commands.)
The simplest way to recover is to use git stash branch. Pick a new branch name, one that you do not yet have. For illustration I will use saveme, which is a terrible name and you should choose a better one.
git stash branch saveme
This will take your existing git stash, create a new branch using the commit that was current when you ran git stash save. It will then restore your index (staging area) to the way it was at the time you ran git stash save, and restore your work-tree to the way it was at the time you ran git stash save. You can now commit the index:
git commit -m 'save index as a commit'
and then commit the rest of the work-tree if there is anything else to commit:
git add --all
git commit -m 'save everything else as a commit too'
I will add, at the end of this answer (in another edit), a pictorial diagram of what happens with this entire sequence, starting from the first git adds and going through the git stash save and git reset --hard HEAD^ and on to the final git stash branch.
There is one caveat: your index and work-tree must be clean to use git stash branch. If you have uncommitted work, you probably should commit it now, or throw it all out with git reset --hard. Of course, either one has consequences:
If you run another git stash save, the earlier saved stash gets "pushed up" from stash#{0} to stash#{1}. You will then have to use:
git stash branch saveme stash#{1}
to convert that stash to a branch.
If you choose to use git reset --hard, you lose any uncommitted work you have, so be sure that this is OK.
Pictorial diagram
Let's take a look at a hypothetical terminal session, and see what happens with your commits and branches as you work.
$ cd my-git-project
At this point, you are in a Git work-tree. The work-tree is where your files are in their normal form, that the rest of the computer (and you) can work with, instead of their Git-only form, where Git saves every version of every file you or anyone else has ever committed. You are on some branch—let's say master, just for concreteness. This branch has some set of commits, ending in what Git calls the tip commit of that branch. The branch name remembers the hash ID of this tip commit:
...--F--G--H <-- master
Each uppercase letter represents a normal, ordinary commit. (In other words, these stand in for the incomprehensible hash IDs that are the actual names of each commit.) Commit H is the latest one. If your index / staging area and work-tree are "clean", the files in them match those in commit H.
Now you make some changes, and stage some or all of them:
$ ... edit some files ...
$ git add file1 file2 ...
The staging area, aka index, is now not "clean": it no longer matches commit H. Instead, it has copies of the edited and added files.
Your work-tree may or may not match your index. If it does match your index, and if you were to run git commit, Git would make a new commit out of your index (that's what the index / staging-area is for, mainly: to build the next commit), and then your index would match your commit and be clean. If your work-tree matches your index, that too would then be clean. This would look like:
...--F--G--H--I <-- master
where I is the new commit, made from your index.
Instead, though, you ran git stash save. What this does is make two commits, neither of which is on the branch:
...--F--G--H <-- master
|\
i-w <-- stash
The first (lowercase i) commit is the same commit that git commit would have made. It's just not on branch master; it's part of this two-commit "stash bag". The second commit, w, is peculiar: it looks to the rest of Git like a merge commit, but in fact it's just a commit of your work-tree state, even if that's the same as the index state in i.
After making these two stash-bag commits, git stash resets (cleans) your index and work-tree, a la git reset --hard HEAD. So now your index and work-tree match commit H again.
Next, you say you ran git reset --hard HEAD^. This does three things: it resets the index and work-tree state to the state of the selected commit, which is the one just before H; and it makes the name master point to the selected commit as well. So now your repository looks like this:
...--F--G <-- master
\
H [remembered in reflogs, *and* preserved via the stash]
|\
i-w <-- stash
Note that the stash-bag is still there, and still find-able by the name stash. The two stash-bag commits remember commit H by its hash ID. Meanwhile, the name master now remembers the hash ID for commit G instead—and your index and work-tree are "clean", i.e., match that for G.
If you now run git stash branch saveme, this is what Git does in terms of commits:
...--F--G <-- master
\
H <-- saveme
|\
i-w [abandoned]
The index is re-loaded from the i commit, and the work-tree is re-loaded from the w commit. If you now run git commit you get:
...--F--G <-- master
\
H--I <-- saveme
since Git saves the index as a new commit I. The work-tree remains unchanged; if it's clean with respect to I, it's now all clean, and if not, you can git add any remaining changes and commit them:
...--F--G <-- master
\
H--I--J <-- saveme
and now everything is saved permanently (or until you delete the saveme branch) in plain, ordinary commits that you can work with in the usual ways. Note that commit H, which you threw into the recycling bin with git reset --hard HEAD^, has come back on the new branch.
Original answer
I should also add that I had only added the storyboards to the stage and hadn't committed them yet at the time of the reset ...
This makes things harder, because:
... so today I was using the git reflog command
git reflog looks only at abandoned commits.
... in hopes that they were in the lost and found.
They may still be! The "lost and found" is separate from the reflogs.
I had read that the garbage collection doesn't happen for a month so I don't think (I hope) they're just gone
The 30-day grace period is specifically for commit objects that are remembered in reflogs, which these are not. However, all objects get a 14-day grace period. The clock starts at the time you git add the file to the staging area. (Even once the clock runs out, it takes a later git gc --auto to make the files go away, but it's hard to know when that will happen.)
Actually finding your files is a bit trickier. Run:
git fsck --lost-found
which, as the documentation says:
--lost-found
Write dangling objects into .git/lost-found/commit/ or
.git/lost-found/other/, depending on type. If the object is a blob,
the contents are written into the file, rather than its object
name.
Since you did git add these files, and they presumably never were in any commit, they will be "dangling" objects of type "blob". The git fsck command will print a bunch of incomprehensible hash names. You can then change into the .git/lost-found/other/ directory and examine all the files there, which all have these hash names. In amongst all these files, the contents you git added will appear.
For each such file, figure out whether it should be saved away under which sensible file name, and move the file out of the lost-found/other area to one of that name, and you have that file back.
Related
I know git stash, but somehow either I am doing something wrong or my problem is not as common as I think.
Scenario: I am coding, committed and pushed a version, doing further code, then to make a decision I would like to test something. For that, I'd love to save the current local files away and return to that state later on to try another solution. Note: in an intermediate un-committed state. Something one would do normally by zipping the project folder and restoring it later.
git stash for me has the crux, that I cannot tell it to simply re-apply the stashed content, ignore anything else, simply recover what was stashed. With git stash apply --force I get (of course) warnings that files are not committed.
Any help?
Use git checkout instead of git stash apply:
$ git checkout stash -- .
This will restore all the files in the current directory to their stashed version.
If I understand the question correctly you can store all untracked files with git stash --include-untracked (or git stash -u for shorten).
After you finish with the tests just revert the stash with git stash pop.
I've made a stupid error which has messed up my database on a Rails App I'm working on. Luckily I'm on a branch and haven't committed any changes so the version on Git is in working order.
How do I now pull through the Git version and update to Sublime so I can carry on working as if nothing happened?
I've just done git pull origin master but it says up to date so I've obviously done something wrong.
I'm not keen on a db:drop so I'd rather do it this way if possible.
You can't pull again, because you already pulled every commit from your remote.
Add changes, stash them, remove the stash:
git add --all && git stash && git stash drop
This will remove every uncommited change and bring you back to the latest commit on the current branch.
git checkout 01h5y77d (find this in git, a version of the app which works)
This would print "HEAD is now at 01h5y77d..."
You don't have to commit because you did not commit the mistakes yet :)
I moved my bundle directory for my ruby gems, but forgot to add the new directory to the .gitignore. So now my GIT is trying to push all the gems as well. I googled around, but I can't find a way to reset my GIT or remove the new bundle directory from the index.
Any ideas?
You can back them up(ie. move them out), get your gitignore adjusted, do a commit with this .gitignore and removals, then put them back after, then push.
So like this
let git commit them (not push them) (suspect you already did this part, which is why your saying they are tied in now)
move them out of your project file, and adjust your ignore file now
mv new/gems some/ignored
vim .gitignore
git add. those changes which will set them for removal
git add .
git commit which will delete them out of the repo (that which will be pushed)
git commit -m "quick removal of supposed ignored gems"
now move your files gems back into their new ignored place
mv some/ignored/gems new/
git status
you shouldn't see them listed anymore. now its safe to do your push
git push
Your mistake will become part of history, as well it should, to get you into the proper habit of keeping commits, and not rebasing. Then you will see exactly what you did, and be able to back track easier. Erasing mistakes can be costly, its best to just let the commit be if its a mistake, and add another commit to fix. If pushing is involved this all can be done before pushing.
Dont push until its well and ready. spot qa test it after making adjustments one last time is a good habit just before pushing. That gives you one last time to correct any mistakes you missed before release.
So never hesitate to commit, commit, commit! Commit frequently, at logical breakpoints, and note your changelog briefs in bullets (hyphens) as comment -m "new release of blah blah, - problem 1 fixed - problem 2 fixed - etc.." on each commit
I have an iOS project on XCode. I've been working off of a branch for some time. I've made particular changes to a file and have been committing the branch for some time. When I moved to an old branch, merged the code, and deleted the most recent branch, I realized this file was never updated to Git. I don't have a .gitignore file.
All my other files were pushed except for this particular set of header and main Objective-C files. I have no idea why the code was never pushed up. I've spent quite a bit of time working on this and losing this updated file is a great blow to me. When I moved to an older commit from the deleted branch the file took its original form.
What could have caused this and is there any wy for me to fix this?
UPDATE
This is not my first rodeo with git. Let me further explain.
Every commit I've made I've used git add . and followed up with git commit and git push respectfully.
I've attempted to pull the branch from the remote repository but the file does not reflect all of the changes I've made to it as of my most recent commit.
You second question - how do I get the code I had on the file that I just deleted.
Here's how -
Create a new branch -
git checkout -b newBranch
Perform a RefLog and get the commits from it -
git reflog | grep commit
Now, you should get a list of commits like this -
d2456b7 HEAD#{1}: commit (merge): Merge
354dce1 HEAD#{3}: commit: 4
8c01ff7 HEAD#{6}: commit: 3
1ab4588 HEAD#{7}: commit: 2
3c419d5 HEAD#{8}: commit (initial): 1
Find the commits that you want, say 3 and 2 from above and do :
git cherry-pick 1ab4588
git cherry-pick 8c01ff7
Do this for all your commits and you should have your branch back.
Alternatively, if you pushed your branch, you could just pull it back.
git pull origin branchName
So i am learning to ever so slowly use git to get me the latest update of RestKit as the old version has retain cycles...fair enough HOWEVER, when i pull using the gitHub Client it does not give me the AFNetworking files, which i was then told use the command
git submodule update --init --recursive
which i do, problem is that i noticed that after running that i run
git submodule status
It has taken me off the master branch and put the HEAD back in thus reverting me to old stuff. and hence back to leaks and stuff.
So i thought maybe i could install using cocoapods or perhaps put a submodule within the restkit submodule for AFNetworking...all did not seem to work and now i have followed this guide How do I remove a submodule? up until the last step as i dont know what committing will do? i hope it does not commit the fact that i deleted everything onto the restkit site? i am so confused, initially all i wanted to do was switch the current branch submodule i have to the master.
Assistance would be much appreciated.
EDIT:
Okay as to answer what Commit does, commit only affects your copy of the repository and will in no way affect the remote "main" repository everyone else gets their code from, so in essence i was able to commit it, then run a brand new submodule from the branch i wanted, But the question still remains Is there a way to switch the branch you pull your data from when using the update with --recursive?
Simply go in th e RestKit directory and type:
git pull origin master
(if you use the master branch of course)
Also, if you need to update all your submodules, just go to the root of your project, and type:
git submodule foreach git pull
git submodule update is confusing, here what it really does:
When you invoke git submodule update it looks in the parent repository for a SHA for each submodule, goes into those submodules, and checks out the corresponding SHAs.
As would be the case if you checked out a SHA in a regular repository, this puts the submodule into a detached HEAD state.
EDIT
To switch branch of a submodule simply, let say 'development', simply do in the submodule git checkout development and then you should be able to do git pull origin development