3

I made a shallow clone of a repository with git clone --depth=1. I made some changes... apparently without understanding the complications of shallow clones... and now want to push the new project to a new remote.

On my main dev machine:

git clone --depth=1 file://old_project new_project
cd new_project
# made a handful of commits here....

I now want to push the project to another machine. On that remote machine I did:

git init --bare new_project.git

And then back on my machine:

git remote remove origin
git remote add origin ssh://<remote host>/path/to/repos/new_project.git

Now when I try to push the project, I get:

fatal: protocol error: expected old/new/ref, got 'shallow 7f6a256...'
fatal: The remote end hung up unexpectedly
Counting objects: 49299, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (44533/44533), done.
error: pack-objects died of signal 13
error: failed to push some refs to '<my new remote>'

What I'd like to do is have the new repo contain the history from the initial shallow clone onward, but still retain the changes made after that point. In other words, I don't want to "unshallow" the branch and pull all the previous history.

Is there a way forward without with just deleting .git directory from the project and starting over?

My machine is running git 1.9.1. The remote is running 1.7.11.7. I can probably update my side with no ill effects, but not the remote as it hosts several other projects that I don't want to risk disrupting.

Brian McFarland
  • 9,052
  • 6
  • 38
  • 56
  • I'm not making this a real answer as it's too speculative, but I *think* the changes in shallow-clone support between 1.7.11.7 and 1.9.1 doom you here. In some cases you could make a tarball of the `.git` directory and copy that directly across, bypassing Git entirely, to do what you want. – torek Jul 09 '16 at 00:16

2 Answers2

5

I would do it as follows:

  1. Create a new root branch:

    git checkout --orphan truncated_master
    
  2. Populate its initial commit with the earliest available commit in your shallow repository:

    START_COMMIT=$(git rev-list master|tail -n 1)
    git checkout $START_COMMIT -- .
    git commit -m "Initial commit"
    
  3. Copy all commits from master to the new branch:

    git cherry-pick $START_COMMIT..master
    
  4. Push the new branch to the new remote:

    git push origin truncated_master:master
    
Leon
  • 31,443
  • 4
  • 72
  • 97
  • 1
    I'll have to give this a shot next time. I gave up and did the quick & dirty `rm -f .git; git init; git add .`. – Brian McFarland Jul 11 '16 at 16:44
  • This helped me. Thanks! – qznc Feb 17 '17 at 15:33
  • This didn't work for me; during `git cherry-pick $START_COMMIT..master`, I got a conflict and had no idea what to do to resolve it. – Jez Jun 22 '18 at 17:07
  • @Jez I had conflicts too, I assume it's because all the changes already existed in the initial commit when I was running cherry pick. The mistake was to run `START_COMMIT=$(git rev-list master|tail -n 1)`. When I picked up the second from the beginning commit, it worked better. – Yuri Pozniak Jul 12 '19 at 00:49
0

Why can't I push from a shallow clone? seems to have some additional commentary. In fact, look at this comment:

Update 2015: with Git 2.5+, you will even be able to fetch a single commit. See "Pull a specific commit from a remote git repository"

So perhaps you can't push, but from the other side, you can pull. Have you tried that?

Community
  • 1
  • 1
David Neiss
  • 8,161
  • 2
  • 20
  • 21