Issue #254: Please warn when newly added git repository is not in 'bare' format
|Reported by:||Karl Goetz|
|Created on:||2016-11-13 23:13|
|Updated on:||2018-05-18 20:13|
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://email@example.com: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.
Comment by Mads Kiilerich, on 2016-11-15 22:22
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
Comment by Søren Løvborg, on 2016-11-16 15:09
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.
Comment by Mads Kiilerich, on 2016-11-16 16:09
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?
Comment by Karl Goetz, on 2016-11-17 04:07
I haven't tried the setting myself but my reading today suggests it should be avoided as its considered dangerous. As such, I've added text to discourage its use and encourage using git clone --bare in my PR.
Comment by Søren Løvborg, on 2016-11-17 15:27
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.
Comment by Andrej Shadura, on 2016-11-17 15:37
I'd argue you should not have detached HEAD in Git repositories which are supposed to be cloned.
Comment by Søren Løvborg, on 2016-11-17 15:53
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.
Comment by Thomas De Schampheleire, on 2018-05-18 20:13
Fixed with b57baf83dc3d