简体   繁体   中英

Added commits in the wrong git repository

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?

  1. Clone your git repository. This is really not necessary, but it's probably a good idea to do this in a dedicated clone.

  2. 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.

  3. In the newly-created clone: check out the branch where the commits should've gone in the first place.

  4. 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.

  5. When you're done, push the branch.

  6. 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.

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:

  1. Create child repo
  2. Add parent repo as a remote of child and fetch changes
  3. Remove commits from parent repo
  4. 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

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 git@github.com: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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM