Please warn when newly added git repository is not in 'bare' format

Issue #254 resolved
Karl Goetz created an issue

Hi,

I decided to try and import some existing repositories to kallithea and they appeared to work. - I took my existing git repositories - synced them from my laptop to my repositories directory - ran Remap and Scan

Kallithea detected the repositories, showed them in the UI, let me change settings and let me add the repository as a git remote.

The repository in Kallithea looks like this

root@kallithea-combined:/srv/kallithea/repositories# ls -lha test-git-repo/
total 12K
drwxr-xr-x 3 root root 4.0K Nov 14 09:45 .
drwxr-xr-x 6 root root 4.0K Nov 14 09:48 ..
-rw-r--r-- 1 root root    0 Nov 14 09:45 file
drwxr-xr-x 8 root root 4.0K Nov 14 09:45 .git
-rw-r--r-- 1 root root    0 Nov 14 09:45 test

Unfortunately (for me), when trying to push the failure occurs.

Karls-Air:test-git-repo kgoetz$ git push
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 259 bytes | 0 bytes/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To http://192.168.1.17:5000/test-git-repo
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'http://kgoetz@192.168.1.17:5000/test-git-repo'
Karls-Air:test-git-repo kgoetz$ 

While I think its an entirely reasonable error, i wonder if kallithea could could convert the non bare repositories to bare? Converting is a simple process

root@kallithea-combined:/srv/kallithea/repositories# cd test-git-repo/
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# ls -lh
total 0
-rw-r--r-- 1 root root 0 Nov 14 09:45 file
-rw-r--r-- 1 root root 0 Nov 14 09:45 test
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# rm *
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# mv .git/* .
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# rmdir .git/
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# git config --bool core.bare true
root@kallithea-combined:/srv/kallithea/repositories/test-git-repo# ls -lh
total 44K
drwxr-xr-x 2 root root 4.0K Nov 14 09:45 branches
-rw-r--r-- 1 root root  577 Nov 14 09:45 COMMIT_EDITMSG
-rwxr--r-- 1 root root   91 Nov 14 10:11 config
-rw-r--r-- 1 root root   73 Nov 14 09:45 description
-rw-r--r-- 1 root root   23 Nov 14 09:45 HEAD
drwxr-xr-x 2 root root 4.0K Nov 14 09:47 hooks
-rw-r--r-- 1 root root  209 Nov 14 09:45 index
drwxr-xr-x 2 root root 4.0K Nov 14 09:58 info
drwxr-xr-x 3 root root 4.0K Nov 14 09:45 logs
drwxr-xr-x 9 root root 4.0K Nov 14 09:58 objects
drwxr-xr-x 4 root root 4.0K Nov 14 09:45 refs

Which allows pushing to work.

Karls-Air:test-git-repo kgoetz$ git push
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 259 bytes | 0 bytes/s, done.
Total 2 (delta 0), reused 0 (delta 0)
To http://192.168.1.17:5000/test-git-repo
   07e4b1e..15774e0  master -> master
Karls-Air:test-git-repo kgoetz$ 

If thats deemed to dangerous (data loss issues perhaps?) if Kallithea could refuse to import anything except bare repositories that would help too.

I'm happy to contribute some documentation on importing repositories 'the right way' if it would be helpful.

thanks,

Comments (8)

  1. Mads Kiilerich

    I am not a git user, but I understand that the problem is that it in git not is possible to push to a branch that is checked out (because that would leave the head detached). But also, it seems like you can't have a non-bare git repo without anything checked out. So yes, Kallithea should probably not try to support non-bare Git repos.

    This must also cause problems for "Admin > Settings > VCS > Update repository after push". For Git, updates must require non-bare repositories ... and for this reason, it can't have that. Some contributor could probably help out clarifying things in that area too ;-)

    Also: the usual mode of operation for Kallithea is that you create a repository through the web interface and then you push to it. You seem to be doing stuff behind the scene where Kallithea can't control anything. Then it is up to the admin to do it in a way works. You have found some dos and don'ts that should be documented. Contributions to documentation or code are much appreciated!

    If admin puts non-bare repositories in the Kallithea folder, then it seems like a very bad idea that Kallithea should do risky and destructive modification of these repositories.

    Something like this might help skipping:

    --- a/kallithea/lib/utils.py
    +++ b/kallithea/lib/utils.py
    @@ -230,4 +230,7 @@ def get_filesystem_repos(path):
                 cur_path = os.path.join(root, subdir)
    +            if isdir(cur_path, '.git'):
    +                log.warning('ignoring non-bare Git repo: %s', cur_path)
    +                continue
    +
                 if (isdir(cur_path, '.hg') or
    -                isdir(cur_path, '.git') or
                     isdir(cur_path, '.svn') or
    
  2. Søren Løvborg

    As the error message suggests, you just need to set receive.denyCurrentBranch=ignore either in the per-repo gitconfig or the www-user (or whatever user Kallithea runs as) git config.

    Possibly this should be documented in the Kallithea docs.

  3. Mads Kiilerich

    If that is an ok solution, then I guess Kallithea should set that option in non-bare repos it see ... or somehow pass that option when pushing?

  4. Søren Løvborg

    Well, the "danger" is that on push Git will move both the HEAD and branch pointer, but not update the working directory. So the result is not a detached HEAD, but rather that the HEAD stays attached and working directory files will shows as modified/missing/etc. in git status (because they no longer match HEAD).

    I assume another workaround is to explicitly detach the head e.g. git checkout --detach master. The working directory will obviously not be updated on push (since only the branch moved and HEAD is unchanged), but it should remain "git status" clean.

  5. Andrej Shadura

    I'd argue you should not have detached HEAD in Git repositories which are supposed to be cloned.

  6. Søren Løvborg

    Oh, right, Git uses the HEAD to determine the repository default branch, I had forgotten that. So yeah, the --detach workaround is not a good idea.

    Anyway, just setting receive.denyCurrentBranch=ignore and getting a dirty working directory on push is nothing dangerous either (no risk of data loss, for instance)... though I guess it could be considered a bit surprising.

  7. Log in to comment