688

I have a working copy of the project, without any source control meta data. Now, I'd like to do the equivalent of git-clone into this folder, and keep my local changes.

git-clone doesn't allow me to clone into an existing folder. What is the best practice here?

Promise Preston
  • 24,334
  • 12
  • 145
  • 143
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • 4
    Better discussion is [here](http://stackoverflow.com/questions/2411031/how-do-i-clone-into-a-non-empty-directory). – cdunn2001 Nov 27 '13 at 23:59
  • Please advice: Wouldn't be simplier, on this case, to: a) copy paste the structure to a temp folder. b) do `git init` on the wanted empty folder. c) copy the content to that folder, and make `git add .` ? – MEM Sep 01 '14 at 12:51
  • 1
    @MEM I like this answer more, but either works... http://stackoverflow.com/a/5377989/11236 – ripper234 Sep 02 '14 at 21:59
  • 2
    @ripper234 - Yes. I was on the same situation and I just did those steps, and no issues. All clean and nice. I guess it's a matter of preference, the bottom line being, that both work, as you state. Cheers. – MEM Sep 04 '14 at 11:01
  • 2
    This is so crazy there is no a clean way to achieve it, so useful when you want to clone a projet to a mounted share folder. – Thomas Decaux Sep 03 '16 at 08:09
  • 1
    Possible duplicate of [How do I clone into a non-empty directory?](https://stackoverflow.com/questions/2411031/how-do-i-clone-into-a-non-empty-directory) – Tobias Kienzler Aug 15 '17 at 05:33
  • Clone in from the parent location. – klewis Mar 25 '20 at 22:56

17 Answers17

799

This can be done by cloning to a new directory, then moving the .git directory into your existing directory.

If your existing directory is named "code".

git clone https://myrepo.com/git.git temp
mv temp/.git code/.git
rm -rf temp

This can also be done without doing a checkout during the clone command; more information can be found here.

Community
  • 1
  • 1
amicitas
  • 13,053
  • 5
  • 38
  • 50
  • 52
    Note that this is exactly the suggestion from @ChrisJohnsen that he left in the comments. I found it useful and wanted to make it into an actual answer. Chris, if you end up putting up an answer, I'll happily delete this one. – amicitas Dec 13 '12 at 03:12
  • 3
    Thanks! Though this is missing a step like "git checkout -- ." as it thinks all the files are deleted, right? – mrooney Dec 15 '12 at 19:39
  • 2
    No, as long as you use `git clone` as the first command, no further checkout command is necessary. If you instead use something like `git clone --no-checkout` in that first step, then after the .git directory is moved it will be necessary to use `git reset HEAD` to tell git that the files have not been deleted. – amicitas Jan 03 '13 at 22:39
  • this works as @amicitas indicated. I did have some lingering "modified" files that needed to be committed, but otherwise was clean to set up this way. thanks! – TheZenker Mar 20 '13 at 14:32
  • This is a very useful answer. Especially if you only commit files which change during development. Great for those who use programming frameworks. – enchance Feb 06 '14 at 17:44
  • 5
    I would add this as third step: mv temp/.gitignore code/.gitignore – Daniel Aranda Feb 26 '15 at 21:27
  • @DanielAranda this would only be necessary if the .gitignore file were checked into the repository but somehow not in the directory with the existing code. If this is the case then other work will most likely be needed to bring the code directory into sync with the repository. – amicitas Mar 17 '15 at 17:22
  • The accepted answer is not the best answer for cloning a repo into an empty directory. Instead you should run the git clone command with a period at the end. That will cause the repo to be downloaded to the current directory. – okTalk Mar 02 '17 at 17:10
  • using `git init` and `git fetch/pull` as describe in other answer is truer to git functionality IMO – Eddie Jul 31 '17 at 00:11
  • This is a very useful answer. I was spending nearly hours before hitting this one. – Masud Rahman Jun 19 '18 at 18:59
  • what happens if one of the files has been modified, would git know? – Kalpesh Soni Nov 09 '18 at 16:24
  • 1
    @KalpeshSoni, yes git will know about the modified files and it will be possible to see the changes using the normal git commands such as `git status`. – amicitas Nov 20 '18 at 12:59
  • Not that `mv` cannot merge directories and overwrite files within those directories. For that you need `rsync`. Bases on answer by @zwets: https://askubuntu.com/a/269818/648886 – Ken Apr 03 '19 at 11:42
  • I do `git pull origin master` after the copying of the .git dir. I get fatal: 'origin' does not appear to be a git repository fatal: Could not read from remote repository. – Timo Nov 19 '20 at 12:28
  • @Ken, do I need a git repo to copy the .git in or can I use the code dir without having done git init? According to you, code also needs to be a git repo. If code has to be "gitted" do I have to set the remote or will it be set when copying .git? – Timo Nov 19 '20 at 12:32
  • This is a great solution. It even works when there are no files in the remote repo. Then I just used ‘Add’ in SourceTree and commit/push to the remote repo. Perfect... – Charles Robertson Apr 29 '21 at 12:54
405

Don't clone, fetch instead. In the repo:

git init
git remote add origin $url_of_clone_source
git fetch origin
git checkout -b master --track origin/master # origin/master is clone's default

Then you can reset the tree to get the commit you want:

git reset origin/master # or whatever commit you think is proper...

and you are like you cloned.

The interesting question here (and the one without answer): How to find out which commit your naked tree was based on, hence to which position to reset to.

Albireo
  • 10,977
  • 13
  • 62
  • 96
Andreas Krey
  • 6,426
  • 2
  • 18
  • 13
  • 10
    I am not a fan of this - per github setup "Tip: The credential helper only works when you clone an HTTPS repository URL." I was using credential helper and this sent me down a long, fairly fruitless rabbit hole. – Andrew Oct 24 '13 at 20:49
  • 7
    'git checkout --track origin/master' also work well instead of 'git checkout -b master --track origin/master'. The reset is not needed. – felipecrp Apr 06 '14 at 02:51
  • 2
    I was getting the error "Git error: The following untracked working tree files would be overwritten by checkout", so I add this command: git clean -d -fx "" – shakaran Jun 21 '15 at 03:36
  • @shakara I had the same problem, what I did was add the --force option. This would allow me to keep unique/untracked files and overwrite the conflicts. In my case I wanted to update local files with their corresponding files in the remote repo and keep unique files on local server. – Fermin Arellano Jun 04 '16 at 15:42
  • this worked well for me, cloning into an empty folder when I didn't have permissions to create a directory to clone into. – dmgig Jan 31 '17 at 15:55
  • 1
    definitely not advisable in all situations, but this is exactly what I needed. – Chaim Eliyah May 04 '17 at 21:57
  • There I'm not looking a moment, and next time I do look the answer makes me scratch my head - my original answer didn't do the checkout on purpose; to not touch any existing file and avoid the 'overwritten' part. – Andreas Krey May 06 '17 at 17:25
  • 2
    @AndreasKrey Your original answer (which I went into the edit history to see) does exactly what is needed by the question (and me). The changed answer barfs at the checkout without using -f, which discards the local changes and is exactly what I *don't* want. If I were you I'd consider rolling back to your original answer. – Ajean Jul 18 '18 at 18:23
  • Worked for me well without `git checkout ...` line. I did not want to overwrite local changes, while checkout tried to do that. – Yaroslav Stavnichiy May 10 '20 at 19:08
  • 1
    To completely reset the local folder, after adding the remote execute `git reset origin/master --hard` – Shanerk Jun 03 '20 at 14:05
  • Github by default primary branch is `main` instead of `master`. So use the command `git checkout -b main --track origin/main` instead – joshlk Oct 22 '20 at 13:59
139

The following i did, to checkout master branch in an existing directory:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft
alexwenzel
  • 2,361
  • 2
  • 15
  • 18
  • 16
    Actually this does exactly what the OP (and me) *don't* want, which is to overwrite local changes. – Ajean Jul 18 '18 at 18:24
  • My upvote indicates that this helped ME, not that is is the best answer to the OP's question. – TecBrat Sep 07 '18 at 04:52
  • 4
    Can someone explain why the `-t` flag is used here? – jfowkes May 17 '19 at 20:17
  • 1
    From `git checkout --help`, `-t` or `--track` are used to make the specified branch the default upstream branch. As far as I know it's the equivalent of `git push -u *branch*`, so that from then on you can just do `git push`. I don't personally know how it affects `git checkout`, but I'd guess in the same way. – Hashim Aziz Sep 10 '19 at 22:22
  • If you have submodules, I don't think this will work either. – emersonthis Apr 14 '20 at 15:58
  • Perfect clean answer if you want any local files that _aren't_ in the repo to be left as-is, and any that _are_ to be modified (if necessary) to match the repo contents. – Mere Development Mar 15 '22 at 11:56
50

Using a temp directory is fine, but this will work if you want to avoid that step. From the root of your working directory:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master
eckes
  • 10,103
  • 1
  • 59
  • 71
user1055643
  • 4,931
  • 1
  • 15
  • 3
  • 28
    `git reset --hard origin/master` will remove any local files. – Mouad Debbar Nov 04 '13 at 05:34
  • 3
    to add to what's already pointed out above, the difference between `hard` and `mixed` is that mixed will keep local changes (so if you later try to pull it'll show you e.g. *Cannot pull with rebase: You have unstaged changes. Please commit or stash them*), while hard will discard those local changes – ᴍᴇʜᴏᴠ Jun 11 '17 at 23:40
  • You mis spelt remote. – Glenn Dayton Jun 22 '17 at 19:44
  • I think this works as required, if `git checkout -- .` is run last. Otherwise anything that wasn't in the DIR when you cloned is staged as deleted. – Mere Development Mar 15 '22 at 11:54
43

I'd git clone to a new directory and copy the content of the existing directory to the new clone.

jhwist
  • 15,201
  • 3
  • 40
  • 47
  • 4
    if you do that, make sure you review the diff before committing very carefully - this is an absolute classic case where you can accidentally revert changes that were made in the source repo since whenever you got your working copy - because there isn't enough info in the working copy to figure out what are changes you made vs what it was like before you started making changes, to merge with other changes made in the repo. I've seen this happen time and time again in this situation, to the point where I "strongly discouraged" myself and people I worked with from ever doing it. – Ben Clifford Mar 21 '11 at 14:41
  • 79
    `git clone wherever tmp && git mv tmp/.git . && rm -rf tmp` In other words, moving the `.git` dir out of a temporary clone seems simpler than cleaning out the working tree of the clone and copying the existing files there. – Chris Johnsen Mar 22 '11 at 10:45
  • 1
    @ChrisJohnsen: you should have made it into an answer, that's definitely the best way to do it imho – Stefano Sep 22 '11 at 08:49
  • 2
    @ChrisJohnsen `git mv tmp/.git .` returns `fatal: cannot move directory over file, source=tmp/.git, destination=.git` for me. Anyone know what the issue is? – Dennis Nov 10 '12 at 08:17
  • 7
    @Dennis, It is a typo: that command should be plain `mv`, not `git mv`; though this does not explain why you have a `.git` file already there (containing `gitdir: some/path/to/a/git-dir`, a “gitfile”; if it were not there, then you would have seen `fatal: Not a git repository (or any of the parent directories): .git` instead). – Chris Johnsen Nov 10 '12 at 19:01
12
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed
return1.at
  • 2,992
  • 3
  • 23
  • 26
9
git init
git remote add origin git@github.com:<user>/<repo>.git
git remote -v
git pull origin master
nwillo
  • 1,204
  • 9
  • 9
  • This would fail if the current working copy has files that are not present in the pulled branch: "*The following untracked working tree files would be overwritten by merge*" (possibly from a different branch). – Gino Mempin Dec 03 '20 at 00:12
  • Yes. This is only if you are pulling your repo before you start working in the directory. @GinoMempin – nwillo Dec 04 '20 at 11:38
  • This worked for me when somehow my .git folder got corrupted and I had to re-clone – Dylan Nicholson May 20 '22 at 10:48
7

To clone a git repo into an empty existing directory do the following:

cd myfolder
git clone https://myrepo.com/git.git . 

Notice the . at the end of your git clone command. That will download the repo into the current working directory.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
okTalk
  • 1,112
  • 1
  • 10
  • 11
5

Lots of answers already to do it the way that the OP asked. But it worth noting that doing it the opposite way around is far simpler:

git clone repo-url tmp/
cp -R working/ tmp/

You now have the desired target state - fresh clone + local-changes.

Andrew
  • 2,943
  • 18
  • 23
3

This is the Best of all methods i came across

Clone just the repository's .git folder (excluding files as they are already in existing-dir) into an empty temporary directory

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp //might want --no-hardlinks for cloning local repo

Move the .git folder to the directory with the files. This makes existing-dir a git repo.

  1. mv existing-dir/existing-dir.tmp/.git existing-dir/

Delete the temporary directory

  1. rmdir existing-dir/existing-dir.tmp

  2. cd existing-dir

Git thinks all files are deleted, this reverts the state of the repo to HEAD.

WARNING: any local changes to the files will be lost.

  1. git reset --mixed HEAD
Amirtha Rajan
  • 605
  • 10
  • 19
1

There are two approaches to this. Where possible I would start with a clean folder for your new git working directory and then copy your version of things in later. This might look something like*:

mv $dir $dir.orig
git clone $url $dir
rsync -av --delete --exclude '.git' $dir.orig/ $dir/
rm -rf $dir.orig

At this point you should have a pretty clean working copy with your previous working folder as the current working directory so any changes include file deletions will show up on the radar if you run git status.

On the other hand if you really must do it the other way around, you can get the same result with something like this:

cd $dir
git clone --no-checkout $url tempdir
mv tempdir/.git .
rmdir tempdir
git reset --mixed HEAD

Either way, the first thing I would do is run something like git stash to get a copy of all your local changes set aside, then you can re-apply them and work through which ones you want to get committed.

* Both examples assume you start out on the shell in the parent directory of your project.

Caleb
  • 5,084
  • 1
  • 46
  • 65
0

Usually I will clone the initial repository first, and then move everything in the existing folder to the initial repository. It works every time.

The advantage of this method is that you won't missing anything of the initial repository including README or .gitignore.

You can also use the command below to finish the steps:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo
0

You can do it by typing the following command lines recursively:

mkdir temp_dir   //  Create new temporary dicetory named temp_dir
git clone https://www...........git temp_dir // Clone your git repo inside it
mv temp_dir/* existing_dir // Move the recently cloned repo content from the temp_dir to your existing_dir
rm -rf temp_dir // Remove the created temporary directory
Mustapha GHLISSI
  • 1,485
  • 1
  • 15
  • 16
0

Just use the . at the end of the git clone command (being in that directory), like this:

cd your_dir_to_clone_in/
git clone git@github.com/somerepo/ .
John F
  • 685
  • 1
  • 8
  • 18
0

For reference, from the Gitlab Commandline instruction:

Push an existing folder

cd existing_folder
git init
git remote add origin <url>
git add .
git commit -m "Initial commit"
git push -u origin master

Or Push an existing Git repository

cd existing_repo
git remote rename origin old-origin
git remote add origin <url>
git push -u origin --all
git push -u origin --tags
Docuemada
  • 1,703
  • 2
  • 25
  • 44
-2

If you are using at least git 1.7.7 (which taught clone the --config option), to turn the current directory into a working copy:

git clone example.com/my.git ./.git --mirror --config core.bare=false

This works by:

  • Cloning the repository into a new .git folder
  • --mirror makes the new clone into a purely metadata folder as .git needs to be
  • --config core.bare=false countermands the implicit bare=true of the --mirror option, thereby allowing the repository to have an associated working directory and act like a normal clone

This obviously won't work if a .git metadata directory already exists in the directory you wish to turn into a working copy.

Araxia
  • 1,136
  • 11
  • 22
ThorSummoner
  • 16,657
  • 15
  • 135
  • 147
  • 1
    Note that this technique will result in the `[core]` section of the local config including both `bare = true` _and_ `bare = false`. More problematic is that it will have the wrong values for the `origin` remote, with the `[remote "origin"]` section including `mirror = true` and a fetch spec that will not work properly with a working copy. After fixing these issues, cloning normally and moving the new working copy's `.git` will have been more efficient. – Araxia Aug 15 '14 at 00:14
-3

if you are cloning the same repository, then run the following snippet through the existing repository

git pull origin master
Mohsin Mahmood
  • 3,238
  • 3
  • 21
  • 25