How to convert a normal Git repository to a bare one?
Asked Answered
M

18

690

How can I convert a 'normal' Git repository to a bare one?

The main difference seems to be:

  • in the normal Git repository, you have a .git folder inside the repository containing all relevant data and all other files making up your working copy

  • in a bare Git repository, there is no working copy and the folder (let's call it repo.git) contains the actual repository data

Mirilla answered 4/2, 2010 at 13:18 Comment(5)
Presumably this is a shorter method: mv repo/.git repo.git; rm -rf repoGoral
Yes, true. When I wrote the question, this was just the snippet of my history, that I executed the other minute.Mirilla
@eegg Use && instead of ; in case mv fails!Milewski
git switch --orphan some_new_name would remove all files except .git folderIbnsaud
@Martian2020, This is not correct. It removes all tracked files and all the commit history.Palawan
T
720

In short: replace the contents of repo with the contents of repo/.git, then tell the repository that it is now a bare repository.

To do this, execute the following commands:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Note that this is different from doing a git clone --bare /path/to/repo to a new location (as described here).

Consider this scenario

  • Your origin had 100 branches
    • You have only checked out 10 of them locally
    • Your bare repo will only have the 10
  • You send the bare repo somewhere
    • It would be missing 90 repos

If that's your intention, that's fine. If you needed a mirror of the remote/origin, this is not the way.

Theodoretheodoric answered 4/2, 2010 at 15:6 Comment(20)
Thanks for the hint at core.bare. Now, after googling this option, I can confirm it: kernel.org/pub/software/scm/git-core/docs/git-config.htmlMirilla
Can I go ahead and delete any branch/remote information left in the config file? I'd previously clones from another and am switching my local copy to be a remote 'master'... thanksPhenomenalism
Thank you! This seems cleaner to me: mv repo/.git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare trueScop
will the files still exist if I did this?Tribromoethanol
This is so much more complicated and fragile than the answer below (git clone --bare /path/to/repo).Mascle
That rm command may need * \.[!.]* rather than * in order to remove dot-files and dot-directories.Adjoint
This command assumes that directory ../ doesn't have .git directory or file inside. If so, it may cause unexpected behavior.Ambiguity
@Ciantic: Again, as I already explained in my comment above, my answer was given 3 years ago, but 5 months ago someone edited the question into something completely different. None of the answers on this page will make any sense anymore. That sequence of commands was directly copied from the question, I just added the last two lines.Reger
.git/index can be removed too, bare repo does not need it.Ecuador
The link that @Mirilla points to confirming the core.bare section has moved to: kernel.org/pub/software/scm/git/docs/git-config.htmlJohan
I find that this answer: https://mcmap.net/q/12172/-when-creating-a-git-repository-that-will-be-on-the-server-can-i-convert-it-to-a-bare-repository-duplicate is much cleaner.Midgard
I tried both this and the following clone option, and the result differs. Also the wiki recommends to use the clone approach, see git.wiki.kernel.org/index.php/…Justin
If you have SourceTree installed you simply can checkout the bare repository to a new folder by... Selecting "New Repository -> Clone from URL", Copy&Paste the path to the local folder into "Source URL", Clicking "Clone". This will create a new folder with the checked out bare repository.Flaunt
Didn't work for me. I had conflicts to resolve which does not make sense.Jubilate
cd repo ; cp -r .git ../repo.gitAmena
I must tell that gitlab thinks the repo is empty after this operationKreindler
This answer does not work as written if the repository you want to convert happens to be a module of an existing repository. In this case .git is not a directory but a file that contains the path to the actual .git directory you must move.Prolamine
Do we have to do this afterward?Statehood
I think log folder need to be deleted too. Also to those 61 people who think git clone is a better solution, try doing it 397 times (re-constructing a vanished server)Red
Do notice that the original config is lost during the process. For example, "the remote", the remote of the new repo created by either git clone --bare A B or git clone --mirror A B. If repo A is cloned from say github, then A has remote url of [email protected]:*/*.git. The repo B would have remote.origin.url=PATH_TO_A.Esse
H
266

Your method looks like it would work; the file structure of a bare repository is just what is inside the .git directory. But I don't know if any of the files are actually changed, so if that fails, you can just do

git clone --bare /path/to/repo

You'll probably need to do it in a different directory to avoid a name conflict, and then you can just move it back to where you want. And you may need to change the config file to point to wherever your origin repo is.

Hokanson answered 4/2, 2010 at 13:26 Comment(6)
Wrong, this method is not the equivalent. Doing a clone doesn't preserve config options, which can be critical to proper operation such as if you use git-p4. Additionally, a clone destroys remotes, again with something like git-p4 you lose the p4/master branch when you clone, so the above approach is preferable.Puck
But you can transfer config options easily by copying the respective parts of the config file. I'd still consider this method to be cleaner than copying and renaming files manually.Bret
This is perfect after a subversion migration since git-svn lacks support for --bare.Manganese
To avoid the name conflict --- git clone --bare /path/to/repo.git /path/to/newbarerepo.gitAustroasiatic
This works as long as you run git update-server-info on the bare repo after creation.Pyroconductivity
WARNING: If you do this and your origin had 100 branches, but you have only checked out 10 of them locally, your bare repo will only have the 10. If you were doing this to send a copy of the bare repo somewhere, they are going to be missing 90 repos.Caboose
N
126

I think the following link would be helpful

GitFaq: How do I make existing non-bare repository bare?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
Nazi answered 3/8, 2010 at 1:46 Comment(2)
Yes, that's quite what I searched, thanks! However, their second proposal (git clone) has the drawbacks that nosatalian mentioned above.Mirilla
The documentation you suggested goes on to say, "A safer method is to let Git handle all the internal settings for you by doing something like this... git clone --bare -l <path_to_repos> <new_dir>"Emphysema
E
80

Unless you specifically want or need to twiddle bits on the filesystem, it really is dead simple to create a bare version of a non-bare repository (mentioned in several other posts here). It’s part of git’s core functionality:

git clone --bare existing_repo_path bare_repo_path

Econometrics answered 8/3, 2013 at 17:36 Comment(3)
Kind of amazing that the far-and-away best answer has 0 votes after > 4 months. The not-very-good-but-dangerous 'accepted answer' has 200!Comparative
Not amazing at all - this answer does not do what the original question asked. It doesn't convert a repo, it clones one, losing information in the process (for example, remote branches).Facer
Of course it begs the question why Git is lossy in the first place (and yeah, I know of git clone --mirror) but to the best of my knowledge the meaning of clone in English isn't "duplicate except for these random unspecified parts" 😉 ... of course the meaning of Git subcommands isn't always exactly self-explanatory, so I guess I'm doing Git wrong by expecting English subcommands to follow the English meaning of the words.Samaritan
T
32

Please also consider to use

git clone --mirror path_to_source_repository path_to_bare_repository

From the documentation:

Set up a mirror of the source repository. This implies --bare. Compared to --bare, --mirror not only maps local branches of the source to local branches of the target, it maps all refs (including remote-tracking branches, notes etc.) and sets up a refspec configuration such that all these refs are overwritten by a git remote update in the target repository.

Tubbs answered 4/8, 2016 at 6:40 Comment(3)
Seems like this is the most concise, complete and safe way to do what the OP wants (vs. just clone). Am I missing something? Was --mirror a relatively recent addition?Lachrymatory
@CraigSilver: No, as I see in the documentation history in such a form the --mirror is available from the version 1.7, so already pretty long. You can check out hereTubbs
After reading this answer, some people might want to read this question: https://mcmap.net/q/12770/-what-39-s-the-difference-between-git-clone-mirror-and-git-clone-bare/11942268Taille
W
11

I just wanted to push to a repository on a network path but git would not let me do that unless that repository was marked as bare. All I needed was to change its config:

git config --bool core.bare true

No need to fiddle with the files unless you want to keep it clean.

Whitechapel answered 24/2, 2016 at 6:30 Comment(2)
This is dangerous, when you also want to work on the work tree of the remote repo. Chances are, that sooner or later you revert a change simply because your remote work tree and index weren't in sync with the repository. I do not recommend this solution, if you do not exactly know what you're doing.Mirilla
True, you should not work on the tree of the remote bare repo.Whitechapel
M
6

i've read the answers and i have done this:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

this will leave the contents of repos/.git as the bare repos.git

Melva answered 12/8, 2010 at 3:11 Comment(0)
M
4

Here's what I think is safest and simplest. There is nothing here not stated above. I just want to see an answer that shows a safe step-by-step procedure. You start one folder up from the repository (repo) you want to make bare. I've adopted the convention implied above that bare repository folders have a .git extension.

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
Mayda answered 14/10, 2011 at 16:3 Comment(2)
this isn't really much safer since you made your backup using git clone. Backup by cloning will cause you to lose some configurations, which in certain cases might be critical for the repository.Suh
Noted. The only configurations I've ever cared about are global to all my local repositories.Mayda
T
4

Simply read

Pro Git Book: 4.2 Git on the Server - Getting Git on a Server

which boild down to

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Then put my_project.git to the server

Which mainly is, what answer #42 tried to point out. Shurely one could reinvent the wheel ;-)

Tubuliflorous answered 4/11, 2015 at 15:42 Comment(1)
I fail to see, what this answer adds, that hasn’t been discussed in arbitrary length in any of the other answers around (including the downvoted). Could you please clarify? (By the way: the Pro Git Book says “This is roughly equivalent to something like…”, and that exact rough equivalence is also already discussed here.)Mirilla
D
3

Here is a little BASH function you can add to your .bashrc or .profile on a UNIX based system. Once added and the shell is either restarted or the file is reloaded via a call to source ~/.profile or source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Once called within a directory containing a .git directory, it will make the appropriate changes to convert the repository. If there is no .git directory present when called, a FAILURE message will appear and no file system changes will happen.

Disarticulate answered 19/4, 2015 at 1:20 Comment(0)
C
2

The methods that say to remove files and muck about with moving the .git directory are not clean and not using the "git" method of doing something that's should be simple. This is the cleanest method I have found to convert a normal repo into a bare repo.

First clone /path/to/normal/repo into a bare repo called repo.git

git clone --bare /path/to/normal/repo

Next remove the origin that points to /path/to/normal/repo

cd repo.git
git remote rm origin

Finally you can remove your original repo. You could rename repo.git to repo at that point, but the standard convention to signify a git repository is something.git, so I'd personally leave it that way.

Once you've done all that, you can clone your new bare repo (which in effect creates a normal repo, and is also how you would convert it from bare to normal)

Of course if you have other upstreams, you'll want to make a note of them, and update your bare repo to include it. But again, it can all be done with the git command. Remember the man pages are your friend.

Coffin answered 4/6, 2014 at 16:38 Comment(1)
Have you bothered to read the other answers? Especially @jonescb's and @nosatalian's comment to it? The "git" method is this: "Do as much as possible with plain text files". You should start investigating the internals of a .git folder. It's highly educating to learn, how the parts fit together.Mirilla
A
2

In case you have a repository with few local checkedout branches /refs/heads/* and few remote branch branches remotes/origin/* AND if you want to convert this into a BARE repository with all branches in /refs/heads/*

you can do the following to save the history.

  1. create a bare repository
  2. cd into the local repository which has local checkedout branches and remote branches
  3. git push /path/to/bare/repo +refs/remotes/origin/:refs/heads/
Abacus answered 3/2, 2017 at 7:8 Comment(0)
F
2

Here is the definition of a bare repository from gitglossary:

A bare repository is normally an appropriately named directory with a .git suffix that does not have a locally checked-out copy of any of the files under revision control. That is, all of the Git administrative and control files that would normally be present in the hidden .git sub-directory are directly present in the repository.git directory instead, and no other files are present and checked out. Usually publishers of public repositories make bare repositories available.

I arrived here because I was playing around with a "local repository" and wanted to be able to do whatever I wanted as if it were a remote repository. I was just playing around, trying to learn about git. I'll assume that this is the situation for whoever wants to read this answer.

I would love for an expert opinion or some specific counter-examples, however it seems that (after rummaging through some git source code that I found) simply going to the file .git/config and setting the core attribute bare to true, git will let you do whatever you want to do to the repository remotely. I.e. the following lines should exist in .git/config:

[core]
    ...
    bare = true
...

(This is roughly what the command git config --bool core.bare true will do, which is probably recommended to deal with more complicated situations)

My justification for this claim is that, in the git source code, there seems to be two different ways of testing if a repo is bare or not. One is by checking a global variable is_bare_repository_cfg. This is set during some setup phase of execution, and reflects the value found in the .git/config file. The other is a function is_bare_repository(). Here is the definition of this function:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

I've not the time nor expertise to say this with absolute confidence, but as far as I could tell if you have the bare attribute set to true in .git/config, this should always return 1. The rest of the function probably is for the following situation:

  1. core.bare is undefined (i.e. neither true nor false)
  2. There is no worktree (i.e. the .git subdirectory is the main directory)

I'll experiment with it when I can later, but this would seem to indicate that setting core.bare = true is equivalent to removeing core.bare from the config file and setting up the directories properly.

At any rate, setting core.bare = true certainly will let you push to it, but I'm not sure if the presence of project files will cause some other operations to go awry. It's interesting and I suppose instructive to push to the repository and see what happened locally (i.e. run git status and make sense of the results).

Five answered 3/1, 2020 at 13:59 Comment(0)
L
0

I used the following script to read a text file that has a list of all my SVN repos and convert them to GIT, and later use git clone --bare to convert to a bare git repo

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt has the format

repo1_name
repo2_name

and users.txt has the format

(no author) = Prince Rogers <[email protected]>

www-data is the Apache web server user, permission is needed to push changes over HTTP

Lubbi answered 3/1, 2017 at 17:39 Comment(0)
F
-1

First, backup your existing repo:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Second, run the following:

git clone --bare -l non_bare_repo new_bare_repo
Festatus answered 23/2, 2012 at 12:54 Comment(1)
What's the intermediate clone for?Comparative
I
-1

Added 2:
After writing the answer realized that accepted answer would likely result in the same result on my PC if followed by git add *.

I got files disappear from my working folder (only .git left), it is again nice and compact by:

git switch --orphan some_new_branch_name 

Then convert to bare if one wants to:

git config --bool core.bare true

That way config including remote link is kept:

$ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=true
remote.origin.url=https://github.com/vmatare/thinkfan.git
remote.origin.fetch=+refs/*:refs/*
remote.origin.mirror=true

Added:
In the comments it is mentioned that it would not remove "any git-ignored files", it such case they need to be additionally deleted manually (or repository itself that is .git subfolder be moved elsewhere).

Notes:
Before core.bare true some actions resulted in errors:

$ git fetch --all
Fetching origin
fatal: Refusing to fetch into current branch refs/heads/devel of non-bare repository
error: Could not fetch origin

some_new_branch_name have not been listed in output of git branch after that. To test further I did git checkout master I got files back and again no some_new_branch_name in output of git branch, so I think new orphan branch would not be added to repository unless some work is done there (and / or commits performed).

Ibnsaud answered 7/12, 2021 at 4:23 Comment(9)
This is something completely different and in no way related to bare or non-bare repositories. Orphan branches are simply branches, that do not share a history with other branches. Therefore, if you create one, Git will show you a now empty work tree.Mirilla
@Boldewyn, yes, the output of git status would show different output, but the question said "bare...there is no working copy". running switch --orphan produces that result. And when I found that QA I was looking for way to remove working copy files w/out breaking consistency of repository, so for my purpose I consider --orphan as best, it does not result in drawbacks mentioned in comments to many top answers (e.g. config lost if clone is used). What problems could it introduce?Ibnsaud
Well, to give you a somewhat close analogy. If my question was, “How do I create an empty folder?” your answer would’ve been “Look! If you run rm -fr * your current folder will be empty! What problems could it introduce?”. Bare repositories behave differently, especially when pushed to. Your repo is still non-bare. Git will, e.g., still complain that it can’t update the working copy of the repository when pushed to. Don’t get me wrong, orphan branches are a wonderful tool. Just for a completely different problem.Mirilla
A quick explanation of bare repos: saintsjd.com/2011/01/what-is-a-bare-git-repository . Use case for orphan branches: shannoncrabill.com/blog/git-orphan-branchesMirilla
@Boldewyn, thank you. Would running after --orphan git config --bool core.bare true convert to bare with all proper behavior?Ibnsaud
Yes, but the switch --orphan would still be unnecessary. You’d simply have an extra branch without commit laying around in the .git folder. And the switch --orphan wouldn’t touch any git-ignored files anyway, so you cannot be sure, that it properly erased all the content of the old worktree folder. Sounds like extra work with additional disadvantages to me.Mirilla
@Boldewyn, running only git config --bool core.bare true on a full working folder does not remove working files, just checked. And nobody here suggested that as an answer.Ibnsaud
@Boldewyn, and w/out --orphan git switch empty1 outputs fatal: invalid reference: empty1. git ignored can be deleted manually, I think I'll add that to the answer for completeness.Ibnsaud
@Boldewyn, thank you for your comments! I've expanded my answer, as I want to use it myself it is already appreciated!Ibnsaud
W
-5

Oneliner for doing all of the above operations:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(don't blame me if something blows up and you didn't have backups :P)

Weixel answered 29/6, 2010 at 9:45 Comment(1)
This doesn't look like a oneliner candidate to me. I understand the negative votes.Orin
P
-9

Wow, it's simply amazing how many people chimed in on this, especially considering it doesn't seem that not a single on stopped to ask why this person is doing what he's doing.

The ONLY difference between a bare and non-bare git repository is that the non-bare version has a working copy. The main reason you would need a bare repo is if you wanted to make it available to a third party, you can't actually work on it directly so at some point you're going to have to clone it at which point you're right back to a regular working copy version.

That being said, to convert to a bare repo all you have to do is make sure you have no commits pending and then just :

rm -R * && mv .git/* . && rm -R .git

There ya go, bare repo.

Predict answered 1/4, 2012 at 13:5 Comment(2)
This will not make it bare enough. Try pushing into it. You need to do git config core.bare true as well.Counseloratlaw
I didn't downvote, but I just wanted to point out that the 1st part of this answer that explains why you would want a bare repo vs a non-bare one is ok, though it doesn't contain enough technical detail, and may be slightly inaccurate. However, for the 2nd part of your answer, while those commands do set up your repo to be bare, Anthony is right, you still need to set git config core.bare true, just like in this answer.Gregale

© 2022 - 2024 — McMap. All rights reserved.