I had a massive git repo because of a huge number of commits, so following advice here I created a shallow clone. I've made changes to this new local repo, and now I want to push to my origin at Github (and then on to my staging and production remotes on Heroku). Perhaps one day I'll learn to read the documentation:
The git clone --depth command option says
--depth Create a shallow clone with a history truncated to the specified number of revisions. A shallow repository has a number
of limitations (you cannot clone or fetch from it, nor push from nor
into it)
So... how can I unpick myself from this situation and push my code to Github?
Git (since 1.8.3) now has an official way to fetch the full history of a shallow clone:
git fetch --unshallow
From the git fetch documentation:
--unshallow
If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations imposed by shallow repositories.
If the source repository is shallow, fetch as much as possible so that the current repository has the same history as the source repository.
I will not agree with the accepted answer for 2 reasons:
- There are many reasons to fail and forget a file
- You lose your commit messages and history
Here are my suggestions:
Graft point
You should have a $GIT_DIR/.git/shallow file with a graft point. If the history is simple enough, this graft point should allow you to push even though documentation says otherwise.
Patches
This allows you to keep commit history and etc:
git format-patch origin..master
Then clone the origin and reapply:
git clone origin_path
cp shallow_clone/*.patch deep_clone
cd deep_clone
git am *.patch
This time you can push !
git push
If you are working in a shallow clone and the lack of history is causing a problem, you can fetch more history with the --depth
option.
git fetch --depth=20
Where 20 is is the amount of commits to fetch. Increase it if that is not enough.
You can also use the --depth
option with git pull
.
I had a similar problem with pushing shallow clone repo to Bitbucket servers and I didn't have an access to old history. Finally, I had found a solution. See a sample script with comments below:
#!/bin/bash
# Fix shallowness
mv .git/shallow .git/info/grafts
git checkout --orphan temp # create temp empty commit
git reset --hard
git commit -m "Init" --allow-empty
# Replace all shallow commits ids with new commit id. I copy-paste all refs from shallow file
git replace 196cdbdb30e608aae2fd7cbe97cc8c0e6fa66c06 <commit_id_of_empty_init_above>
git replace 4c645849b296aaafc1809a9e1537c0fb305167ad <commit_id_of_empty_init_above>
git replace 50eab8bd8c416c47354331211b1efd8688ad8e97 <commit_id_of_empty_init_above>
git replace 649dc7577b87d1b05dff05bf9adc5e46f6612dfa <commit_id_of_empty_init_above>
git replace 6902148fde7b98ff0d6b6c6ebe929590322c95ff <commit_id_of_empty_init_above>
git remote set-url origin http://<username>:<password>@<example.com:port/repo.git> # reference to a remote repo to push
git push origin 'refs/replace/*' # push replace refs to remote repo first
git push -u origin master # push to master, finally
# Clear some garbage just in case
git filter-branch --tag-name-filter cat -- --all # rewrite history
git push --force origin
git fsck # check that everything is ok
Option 1)
If you still have the original repo, just fetch from it before pushing:
git fetch --unshallow
Option 2)
BEWARE! this is only recommended for new repos, as this WILL result in loss of history, and also is highly prone to conflicts!!
If you've already removed the repository where you fetched from,
you need to discard all history with.
git filter-branch -- --all
git push
git filter-branch
: Lets you rewrite Git revision history
--
: separates filter-branch options from revision options
--all
: to rewrite all branches and tags