Reputation: 10862
I was working on a project backed by git and committing along happily. Eventually, I realized that I had forgotten to make a git repository for my project. Instead, my commits were going to a parent repository in the folder that contained my project.
Is it possible to keep these commits, but move them to a completely separate repository?
Upvotes: 1
Views: 135
Reputation: 72855
Assuming that your project looks something like this
project/
file1
file2
file3
your_subdir/
subfile1
subfile2
I'm assuming that the current git repository is the one that tracks project
and that the your_subdir
directory is the place where you added these two new files (perhaps as two separate commits) which you want moved to a separate repository.
What you can do is to split the your_subdir
directory into a separate subtree using
git subtree split -P your_subdir
This will print a single hash of head of a new tree that has only the commits rooted at your_subtree
. Let's assume that it prints abcd
.
Now cut a branch at that commit using
git branch foo `abcd`
Now you can push this branch (perhaps as master
) to a new remote which is created just to house this sub project alone like so.
git remote add subproj [email protected]:sam/subproj.git
git push subproj foo:master
Now, you can either continue using this as is. Or you can reset your master
to where it was before these two commits and add the subproject
as a submodule.
Upvotes: 1
Reputation: 2993
Not exactly keep but copy to new repo. Assume you have 2 directories, parent and child, with child a subdirectory of parent.
You can git init
in child to create a new repository. This doesn't have much effect as yet, but is required if you want to bring over your files to a new repo. To easily copy the commits to your new repo, you need to add parent as a remote and cherry-pick
the commits you want over.
In summary:
cherry-pick
commits from parent repo to child repo using the subtree strategy.Note that the order below is important!
user@COMPUTER /c/projects/parent/child (master)
$ git init
Initialized empty Git repository in c:/projects/parent/child/.git/
user@COMPUTER /c/projects/parent/child (master)
$ git remote add parent /c/projects/parent
user@COMPUTER /c/projects/parent/child (master)
$ git fetch parent
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 7 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (7/7), done.
From c:/projects/parent
* [new branch] master -> parent/master
user@COMPUTER /c/projects/parent/child (master)
$ cd ../
# You could revert the commits too at this point, or delete the files. Your choice
user@COMPUTER /c/projects/parent (master)
$ git rm child/file.txt
rm 'child/file.txt'
user@COMPUTER /c/projects/parent (master)
$ git commit -m "Removed commits for other repo"
[master d228096] Removed commits for other repo
1 file changed, 1 deletion(-)
delete mode 100644 child/file.txt
user@COMPUTER /c/projects/parent (master)
$ git log --oneline
d228096 Removed commits for other repo
5f29100 Some commit I want to really put in child
3263034 Initial commit
user@COMPUTER /c/projects/parent (master)
$ cd child/
user@COMPUTER /c/projects/parent/child (master)
$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
user@COMPUTER /c/projects/parent/child (master)
$ git cherry-pick 5f29100 --strategy=subtree -Xsubtree=child
[master (root-commit) a1b14e4] Some commit I want to really put in child
1 file changed, 1 insertion(+)
create mode 100644 file.txt
user@COMPUTER /c/projects/parent/child (master)
$ ls
file.txt
Note: If you try to cherry-pick before removing from the parent repo you will get something like this:
user@COMPUTER /c/projects/parent/child (master)
$ git cherry-pick parent/master --strategy=subtree -Xsubtree=child
error: The following untracked working tree files would be overwritten by merge:
file.txt
Please move or remove them before you can merge.
Aborting
error: could not apply 5f29100... Some commit I want to really put in child
Upvotes: 1
Reputation: 118435
Clone your git repository. This is really not necessary, but it's probably a good idea to do this in a dedicated clone.
Attach the parent repository (or your clone of the parent repository) where the commits were made, as a remote repository of your newly-created clone.
In the newly-created clone: check out the branch where the commits should've gone in the first place.
At this point, you should be able to individually cherry-pick the commits from the remote repository into the right branch in your clone. See git cherry-pick
documentation for more information. You can use git log
on remotename/branch
to get the hashes of the commits that were made on the parent's repo.
When you're done, push the branch.
Cleaning up the parent repository depends on whether the misplaced commits that were made have not been pushed up yet. If they haven't, you can simply git reset
your parent repository clone, and get rid of them there. If they were already pushed, it's probably better to push a commit to back them out.
Upvotes: 1