Stewart
Stewart

Reputation: 4982

Adding old git history to new repository

I created a git repository and committed content to it.

git clone git://newrepo.com/project.git # Empty repository
tar -xzvf project-0.6.tar.gz -C project     # Fill it with tar contents
cd project
git commit -a
... Do work
... Commit
... Push

But later found a recovered version of the same project with git history, made with an earlier version of the tar.gz.

How can I import the history from the old project into the new one?


I'm thinking I need to do something like this:

git clone git://newrepo.com/project.git                 # Start fresh
cp -r project project_backup                            # Backup the content
cd project                               
git init                                                # Wipe everything
git remote set-url origin git://oldrepo.com/project.git # Point to the old project
git pull                                                # Get clean history
cp -r ../project_backup .                               # Apply new content
git commit -a                                           # One big commit
git remote set-url origin git://newrepo.com/project.git # Point to the new project
git push                                                # Push changes

But I don't think git init works like that. man says it doesn't actually touch the git history. I heard git rebase might be the solution, but I'm not sure how to use it in this context.

In git-manpage format: I'd be turning this:

A---B---C master (oldrepo)

D---E---F master (newrepo)

into

A---B---C---D'---E'---F' master (newrepo)

Edit:

I do have push access to oldrepo. I'm sure I could figure out how to apply my changes to oldrepo, but then how would I replace newrepo with oldrepo?

Edit2

git rebase was suggested. I'm having problems with it. When I resolve the conflicts and finish with the rebase,

git clone [email protected]/project.git project-rebase
cd project-rebase
git fetch --all
git remote add original https://oldrepo.com/project-old.git
git fetch original
git rebase --onto original/master 6210d0b3cf20f506ce0bab7849550b38c9effb15 master
--- resolving conflict ---
git rebase --continue

At this point I hoped we were done. The git log looks great, but:

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 102 and 11 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

nothing to commit, working tree clean'

$ git push origin master
To newrepo.com:project.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:project.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Upvotes: 7

Views: 3058

Answers (3)

Stewart
Stewart

Reputation: 4982

Thanks to Schwern's excellent start the problem is solved. Here is the whole solution:

git clone [email protected]:project.git
cd project
git fetch --all
git remote add original https://oldrepo.com/project-old.git
git fetch original
git rebase --onto original/master 6210d0b3cf20f506ce0bab7849550b38c9effb15 master

# Manual resolution of conflict

git rebase --continue
git push --force origin master      # Need to disable branch protection in gitlab
                                    # Re-enable protection in gitlab

I was missing the --force which replaces the whole remote branch with your locally modified one. Since my repo is in gitlab, the master branch was protected and --force was not allowed. I had to unprotect master temporarily in order to make that command succeed.

Then I continued for each branch:

git checkout --track origin/upstream
git rebase --onto original/upstream 6210d0b3cf20f506ce0bab7849550b38c9effb15    
# Manual resolution of conflict    
git rebase --continue
gir push --force origin upstream

My last branch had no conflicts, so this one was simple:

git checkout --track origin/pristine-tar
git rebase --onto original/pristine-tar 6210d0b3cf20f506ce0bab7849550b38c9effb15
git push --force origin pristine-tar

Upvotes: 4

Schwern
Schwern

Reputation: 164669

Yes, you should be able to use git rebase for this.

Add the old repo as a remote and fetch it.

git remote add original <directory or url>
git fetch original

Now you've got like...

A - B - C [original/master]

D - E - F [master]

Then rebase your work on top of that. You should skip your first commit in the new repo where you added the tarball, commit D here, otherwise that will revert your old work.

git rebase --onto original/master D master

This will rebase from but excluding D, up to and including master. So only E and F which are your patches on top of the source tarball.

          E1 - F1 [master]
         /
A - B - C [original/master]

There may be conflicts.

Upvotes: 9

eftshift0
eftshift0

Reputation: 30156

Add the old repo as a remote, checkout the remote branch (create a local branch for it or work on detached HEAD).... or a revision that very closely resembles what you had on the tar that you used to create the first revision of the project.... cherry-pick the revisions after committing the tar content on top of the branch you are working on.

Upvotes: 1

Related Questions