169

I have a directory gitrepo1. This directory is a git repository.

  • I would like to move this gitrepo1 into another directory newrepo.

  • Directory newrepo should be the new git repository with no loss of git history and should contain the directory gitrepo1.

  • Directory gitrepo1 should just be a directory now (inside newrepo), without any .git index, i.e. it should NO longer be an independent git repository or a submodule.

How can I do this?

NickD
  • 5,937
  • 1
  • 21
  • 38
Pranjal Mittal
  • 10,772
  • 18
  • 74
  • 99

7 Answers7

168

It's very simple. Git doesn't care about what's the name of its directory. It only cares what's inside. So you can simply do:

# copy the directory into newrepo dir that exists already (else create it)
$ cp -r gitrepo1 newrepo

# remove .git from old repo to delete all history and anything git from it
$ rm -rf gitrepo1/.git

Note that the copy is quite expensive if the repository is large and with a long history. You can avoid it easily too:

# move the directory instead
$ mv gitrepo1 newrepo

# make a copy of the latest version
# Either:
$ mkdir gitrepo1; cp -r newrepo/* gitrepo1/  # doesn't copy .gitignore (and other hidden files)

# Or:
$ git clone --depth 1 newrepo gitrepo1; rm -rf gitrepo1/.git

# Or (look further here: http://stackoverflow.com/q/1209999/912144)
$ git archive --format=tar --remote=<repository URL> HEAD | tar xf -

Once you create newrepo, the destination to put gitrepo1 could be anywhere, even inside newrepo if you want it. It doesn't change the procedure, just the path you are writing gitrepo1 back.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • 7
    +1. It's probably worth mentioning [this gotcha](http://stackoverflow.com/a/17747571/761202) affecting repositories created with git version 1.7.8 or 1.7.9 - which can mean moving a git repo makes it unusable (though as indicated it's easily corrected). – AD7six Sep 30 '13 at 14:56
  • 1
    i am on wndows machine and using command prompt. i couldn't find "cp" command. is "cp" command specific to other OS? – LP13 Dec 11 '15 at 17:27
  • 4
    @user3862378, `cp`, like almost every command or function is specific to other OSes. In fact, it's specific to every OS that is not windows. Try calling microsoft and asking them why they aren't POSIX. Anyway, `cp` means copy. `mv` means move. `rm` means remove. You can find windows equivalents. – Shahbaz Dec 13 '15 at 15:39
  • 1
    @Shahbaz Thanks, the solution above creates the following structure "newrepo->.git" and "newrepo->all other files from gitrepo1"...its not putting "gitrepo1" folder inside "newrepo"..i'm curious if creating folders manually in windows and moving ".git" folder under the root folder..would work without affecting the history? – LP13 Dec 14 '15 at 18:29
  • 2
    @user3862378, there is no reason why it shouldn't. `.git/` contains all of the history, which includes your latest commit. Wherever you put it, you have all the history. In fact, if all the files in that directory are different from the original repo where you took `.git/` from, the only thing would be that it tells you some files are deleted and some untracked ones are present. With a `git reset --hard`, the removed files would be recovered automatically! Only thing to note is that just by copying `.git/` you cannot recover the uncommitted changes. – Shahbaz Dec 15 '15 at 14:19
  • But wait I mean wouldn't this all mean that the history in `gitrepo1` gets deleted? I thought the asker wanted no loss of git history. I understood the question as "how do I merge the git history in one repo with another", which is also what I would want to know. Is that even possible? – Marses Oct 01 '20 at 07:21
  • No op says the original directory should be without history. See question. If you want to merge two repos, you can actually do that with git itself, but if they are unrelated repos, I don't see much benefit in that. Feel free to ask a new question for that, but the short answer is to do this in one of the repos: `git remote add other_repo path/to/other/repo; git fetch other_repo`. – Shahbaz Oct 02 '20 at 19:57
  • @Shahbaz What If I wanted to keep `gitrepo1` as a submodule after copying to `newrepo` folder i.e. changes made in the `gitrepo1` folder should not show up in visual studio code when I have the `newrepo` folder added in visual studio code? – Kartik Watwani Jul 15 '21 at 07:28
  • @KartikWatwani, that's a different question. Please ask a new question so it can be found by future readers as well. – Shahbaz Sep 19 '21 at 01:39
  • op wants "new git repository with no loss of git history". Not "without history". "no loss of history" means he does NOT want history to be deleted. – Keith Knauber Aug 11 '23 at 17:55
41

It's even simpler than that. Just did this (on Windows, but it should work on other OS):

  1. Create newrepo.
  2. Move gitrepo1 into newrepo.
  3. Move .git from gitrepo1 to newrepo (up one level).
  4. Commit changes (fix tracking as required).

Git just sees you added a directory and renamed a bunch of files. No biggie.

david.pfx
  • 10,520
  • 3
  • 30
  • 63
11

I am no expert, but I copy the .git folder to a new folder, then invoke: git reset --hard HEAD

gharel
  • 413
  • 4
  • 13
7

To do this without any headache:

  1. Check what's the current branch in the gitrepo1 with git status, let's say branch "development".
  2. Change directory to the newrepo, then git clone the project from repository.
  3. Switch branch in newrepo to the previous one: git checkout development.
  4. Syncronize newrepo with the older one, gitrepo1 using rsync, excluding .git folder: rsync -azv --exclude '.git' gitrepo1 newrepo/gitrepo1. You don't have to do this with rsync of course, but it does it so smooth.

The benefit:

You are good to continue exactly where you left off: your older branch, unstaged changes, etc.

emremrah
  • 1,733
  • 13
  • 19
  • This will just copy the `source` folder to `destination/source`. The correct command is `rsync -azv --exclude '.git' source/ destination/`, which copies contents of `source` folder to `destination` folder. [Some explanation here](https://serverfault.com/questions/529287). – rupinderjeet Feb 27 '22 at 08:44
0

simple way to move a git repository into another directory and make that directory a git repository using mirroring method

git clone --mirror git@example.com/mirror-repository.git

cd mirror-repository.git

push changes to new repository using below command

git push --mirror git@example.com/new-mirror.git

This will get all the branches and tags that are available in the mirror repository and will replicate those into the new location.

Don’t use git push --mirror in repositories that weren’t cloned by --mirror as well. It’ll overwrite the remote repository with your local references (and your local branches).git clone --mirror is prefered over git clone --bare because the former also clones git notes and some other attributes.

0

for me on windows it works with xcopy. copy command does not copy the hidden files. from root folder run this command:

xcopy subfolderofRepo .\ /s /e /h

samsoft
  • 21
  • 7
0

In the end none of these answers worked for me. OP specifically wants "no loss of git history". Most of these answers blow away git history.

I found the answer on another thread, specifically the answer that says to use "git mv" command, which I was not aware of.

Move file and directory into a sub-directory along with commit history

  • To move tracked files, use "git mv".
  • To move untracked files, just move them using "mv".

This process preserves all your history, including uncommitted changes. No need for a clean working copy.

So to answer OPs question, Starting out in the original folder, make another folder with the same name!

$ /Users/me/gitrepo1> mkdir gitrepo1
$ /Users/me/gitrepo1> ls
 .git/
 .gitattributes
 .gitignore
 gitrepo1/
 exampleFile
 exampleDir/
 exampleUntrackedFile
$ /Users/me/gitrepo1> git mv exampleFile exampleDir gitrepo1
$ /Users/me/gitrepo1> git mv exampleUntrackedFile gitrepo1
 fatal: not under version control, source= exampleUntrackedFile, destination= gitrepo1/exampleUntrackedFile
$ /Users/me/gitrepo1> mv exampleUntrackedFile gitrepo1
$ /Users/me/gitrepo1> git status
    renamed:    exampleFile -> gitrepo1/exampleFile
    renamed:    exampleDir -> gitrepo1/exampleDir
Untracked files:
    gitrepo1/exampleUntrackedFile

And finally, rename to newrepo

cd ..
mv gitrepo1 newrepo
Keith Knauber
  • 752
  • 6
  • 13