ChatGPT解决这个技术问题 Extra ChatGPT

Git: What's the best practice to "git clone" into an existing folder?

git

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?

Better discussion is here.
@MEM I like this answer more, but either works... stackoverflow.com/a/5377989/11236
@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.
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.

C
Community

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.


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.
Thanks! Though this is missing a step like "git checkout -- ." as it thinks all the files are deleted, right?
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.
I would add this as third step: mv temp/.gitignore code/.gitignore
@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.
A
Albireo

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.


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.
'git checkout --track origin/master' also work well instead of 'git checkout -b master --track origin/master'. The reset is not needed.
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 ""
definitely not advisable in all situations, but this is exactly what I needed.
@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.
a
alexwenzel

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

This is a great answer and avoids any filesystem finagling.
This should be the accepted answer since it is not a hack.
Actually this does exactly what the OP (and me) don't want, which is to overwrite local changes.
Can someone explain why the -t flag is used here?
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.
e
eckes

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

git reset --hard origin/master will remove any local files.
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
You mis spelt remote.
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.
j
jhwist

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


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.
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.
@ChrisJohnsen: you should have made it into an answer, that's definitely the best way to do it imho
@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, 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).
r
return1.at
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed

Using git reset --hard will nuke the local file changes, specifically NOT what this OP requested. --mixed should be used instead.
--mixed can be omitted since it's the default.
A
Andrew

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.


V
Vadim Kotov

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.


fatal: destination path '.' already exists and is not an empty directory.
The directory must be empty.
The OP is asking for how to clone into an existing project, stating that git clone complains. Bad answer.
This works only when you create new directory, run the above commands without using "git init"
The directory has to be empty in order for this to work, which includes hidden files such as .DS_Store. Create the directory using command line and you won't have issues.
n
nwillo
git init
git remote add origin git@github.com:<user>/<repo>.git
git remote -v
git pull origin master

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).
Yes. This is only if you are pulling your repo before you start working in the directory. @GinoMempin
This worked for me when somehow my .git folder got corrupted and I had to re-clone
A
Amirtha Rajan

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

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.

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

Delete the temporary directory

rmdir existing-dir/existing-dir.tmp 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.

git reset --mixed HEAD


A hard reset seems unwanted in 99% of the cases where you'd need to do this.
C
Caleb

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.


M
Mike Chen

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

M
Mustapha GHLISSI

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

D
Docuemada

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

A
Araxia

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.


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.
J
John F

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

Does not work: fatal: destination path '.' already exists and is not an empty directory.
You can't clone into the not empty directory.
M
Mohsin Mahmood

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

git pull origin master