Reputation: 6445
I have a git submodule (RestKit) which I have added to my repo.
I accidentally changed some files in there and I'd like to go back to the source version. In order to do that, I tried to run
Mac:app-ios user$ git submodule update RestKit
But as you can see here, this did not work as it is still "modified content":
Mac:app-ios user$ git status
...
# modified: RestKit (modified content)
Even
Mac:app-ios user$ git submodule update -f RestKit
doesn't revert locally modified files.
How do I reset the content of that submodule?
Upvotes: 473
Views: 390863
Reputation: 186
I was a bit wary of the reset, hard and force commands, so I did it this way:
Run
git diff | grep Subproject -n2
For each of the affected repo's the folder is above the change, copy the previous commit id, the minus one.
Change into their directory and
git checkout <commitid>
When I check on my main repo after that I'm back to no diff's there.
Upvotes: 0
Reputation: 1932
In my case, I do it this way:
Go to the submodule path
cd <submodule_path>
Check the last commit hash
git log
Reset the change to that last commit hash
git reset --hard <commit_hash>
Upvotes: 2
Reputation: 17727
A more fail-safe method than all previous answers:
git submodule deinit -f .
git submodule update --init
The first command completely "unbinds" all submodules, the second then makes a fresh checkout of them.
It takes longer than the other methods, but will work whatever the state of your submodules.
If your sub-modules have their own sub-modules, instead of second command, try:
git submodule update --init --recursive --checkout
Where --recursive
is obvious, but --checkout
prevents "Skipping submodule ...
" (see skip details).
Upvotes: 545
Reputation: 1512
The currently most voted answer (deinit
and update
) gets rid of every non tracked file.
A way to achieve the same result but keep non tracked files around is to directly checkout all submodules to the commit the parent is pointing to:
git submodule update --checkout --force
The command is a bit faster too.
Upvotes: 3
Reputation: 835
If you want to discard all changes in the entire repository along with submodules, you can use:
git restore . --recurse-submodules
Note that this only undoes all local-changes (in repository, and in all sub modules).
But
git reset ...
takes a target-commit-id as input, and can moveHEAD
to any commit.
Upvotes: 51
Reputation: 7309
My way to reset all submodules (without detaching & keeping their master
branch):
git submodule foreach 'git checkout master && git reset --hard $sha1'
Upvotes: 4
Reputation: 5025
If you want to do this for all submodules, without having to change directories, you can perform
git submodule foreach git reset --hard
You can also use the recursive flag to apply to all submodules:
git submodule foreach --recursive git reset --hard
Upvotes: 401
Reputation: 38166
It is simple:
cd /path/to/submodule/root
git submodule update -f --init .
Most answers are suggesting resetting all the submodule, which I think is not the best approach as there might be legit changes in them.
Upvotes: 12
Reputation: 4544
If there's changes in your submodules, then use
git submodule foreach --recursive git reset --hard
If your changes are remote submodule changes, then use
git submodule update --init
If these changes have been committed, then use
git reset --hard
git submodule update --init
Upvotes: 5
Reputation: 629
First try this, as others have said:
git submodule update --init
If that doesn't work, change to the submodule directory and use the following command to see if there are any changes to the submodule:
git status
If there are changes to your submodule, get rid of them. Verify that you can don't see any changes when you run "git status".
Next, go back to the main repository and run "git submodule update --init" again.
Upvotes: 24
Reputation: 1437
This worked for me, including recursively into submodules (perhaps that's why your -f didn't work, cause you changed a submodule inside the submodule):
git submodule update -f --recursive
Upvotes: 38
Reputation: 117028
For git <= 2.13 these two commands combined should reset your repos with recursive submodules:
git submodule foreach --recursive git reset --hard
git submodule update --recursive --init
Upvotes: 7
Reputation: 1324897
Since Git 2.14 (Q3 2017), you don't have to go into each submodule to do a git reset
(as in git submodule foreach git reset --hard
)
That is because git reset itself knows now how to recursively go into submodules.
See commit 35b96d1 (21 Apr 2017), and commit f2d4899, commit 823bab0, commit cd279e2 (18 Apr 2017) by Stefan Beller (stefanbeller
).
(Merged by Junio C Hamano -- gitster
-- in commit 5f074ca, 29 May 2017)
builtin/reset: add --recurse-submodules switch
git-reset
is yet another working tree manipulator, which should be taught about submodules.
When a user uses git-reset and requests to recurse into submodules, this will reset the submodules to the object name as recorded in the superproject, detaching the HEADs.
Warning: the difference between:
git reset --hard --recurse-submodule
andgit submodule foreach git reset --hard
is that the former will also reset your main parent repo working tree, as the latter would only reset the submodules working tree.
So use with caution.
Upvotes: 14
Reputation: 1531
do 4 steps sequential:
git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f
Upvotes: 57
Reputation: 373
This works with our libraries running GIT v1.7.1, where we have a DEV package repo and LIVE package repo. The repositories themselves are nothing but a shell to package the assets for a project. all submodules.
The LIVE is never updated intentionally, however cache files or accidents can occur, leaving the repo dirty. New submodules added to the DEV must be initialized within LIVE as well.
Package Repository in DEV
Here we want to pull all upstream changes that we are not yet aware of, then we will update our package repository.
# Recursively reset to the last HEAD
git submodule foreach --recursive git reset --hard
# Recursively cleanup all files and directories
git submodule foreach --recursive git clean -fd
# Recursively pull the upstream master
git submodule foreach --recursive git pull origin master
# Add / Commit / Push all updates to the package repo
git add .
git commit -m "Updates submodules"
git push
Package Repository in LIVE
Here we want to pull the changes that are committed to the DEV repository, but not unknown upstream changes.
# Pull changes
git pull
# Pull status (this is required for the submodule update to work)
git status
# Initialize / Update
git submodule update --init --recursive
Upvotes: 3
Reputation: 6735
Well for me, having
git reset --hard
just reset the submodule to the state where it checked out, not necessary to the main's repo referenced commit/state. I'll still have "modified contents" like OP said. So, in order to get the submodule back to the corrects commit, I run:
git submodule update --init
Then when I do git status
, it's clean on the submodule.
Upvotes: 99
Reputation: 9522
Move into the submodule's directory, then do a git reset --hard
to reset all modified files to their last committed state. Be aware that this will discard all non-committed changes.
Upvotes: 273