diff --git a/.gitignore b/.gitignore
index 5a61616fb290520701c3303abe0e4d015c786454..7b45ca3ae4ed5e7dff2ac42b9f2497c70ce28be0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,4 +27,5 @@ nbproject
 /public_html/vendor/medoo/
 /config/_inc_projects_config.php
 /config/inc_projects_config.php
+/config/inc_user2roles.php
 /.vscode/
\ No newline at end of file
diff --git a/hooks/templates/inc_projects_config.php.erb b/hooks/templates/inc_projects_config.php.erb
index 855209a329d1adce63a2f59600c4c55076eefa5c..c972b90a3bd1af34841bc670e8e923081c296542 100644
--- a/hooks/templates/inc_projects_config.php.erb
+++ b/hooks/templates/inc_projects_config.php.erb
@@ -123,12 +123,12 @@ switch (php_uname("n")) {
             $aConfig['mirrorPackages'] = array(
                 'puppet' => array(
                     'type' => 'rsync',
-                    'runas' => '', // www-data', // nur fuer commandline
+                    'runas' => '', // www-data, // nur fuer commandline
                     'target' => 'ladmin@calcium.iml.unibe.ch:/share/imldeployment',
                 ),
                 'puppet.one' => array(
                     'type' => 'rsync',
-                    'runas' => '', // www-data', // nur fuer commandline
+                    'runas' => '', // www-data, // nur fuer commandline
                     'target' => 'copy-deployment@puppet.one.iml.unibe.ch:/var/shared/imldeployment',
                 ),
                 'pkg-server' => array(
diff --git a/public_html/api/index.php b/public_html/api/index.php
index 74a9f2928335ca608a925f929adba69ba048235b..c84e9617d90ec202aa429c8d3e495954c00e63c6 100644
--- a/public_html/api/index.php
+++ b/public_html/api/index.php
@@ -10,6 +10,7 @@
  * 
  * ----------------------------------------------------------------------
  * 2020-06-16  v0.9  <axel.hahn@iml.unibe.ch>  
+ * 2021-03-29  v1.2  <axel.hahn@iml.unibe.ch>  support slashes in branch names
  * ======================================================================
  */
 
@@ -132,11 +133,11 @@
     $aUriSplit= explode('/', preg_replace('/\?.*$/', '', $_SERVER["REQUEST_URI"]));
 
     array_shift($aUriSplit);
-    array_shift($aUriSplit);     
+    array_shift($aUriSplit);
     _wd('<pre>$aUriSplit: '.print_r($aUriSplit, 1).'</pre>');  
     /*
     
-    /api/v1/projects/ci/build?auth=123
+    /api/v1/projects/ci/build/...
     $aUriSplit: Array
         (
             [0] => v1
@@ -173,11 +174,14 @@
 
                     $sPrjId     = isset($aUriSplit[2]) ? $aUriSplit[2] : false;
                     $sPrjAction = isset($aUriSplit[3]) ? $aUriSplit[3] : false;
-                    $sParam4    = isset($aUriSplit[4]) ? $aUriSplit[4] : false;
-                    $sParam5    = isset($aUriSplit[5]) ? $aUriSplit[5] : false;
+                    $sBranch    = implode('/', array_slice($aUriSplit, 4));
+                    
+                    // $sParam4    = isset($aUriSplit[4]) ? $aUriSplit[4] : false;
+                    // $sParam5    = isset($aUriSplit[5]) ? $aUriSplit[5] : false;
                     $sMethod    = $_SERVER['REQUEST_METHOD'];
                     _wd('$sPrjId = '.$sPrjId);
                     _wd('$sPrjAction = '.$sPrjAction);
+                    _wd('$sBranch = ' . $sBranch); 
                     
                     $oCLog = new logger();
                     // try to init the given project
@@ -208,8 +212,8 @@
 
                     switch($sPrjAction){
                         case "build":
-                            if ($sParam4){
-                                $aResult=$oProject->setBranchname($sParam4 . ($sParam5 ? '/'.$sParam5 : ''));
+                            if ($sBranch){
+                                $aResult=$oProject->setBranchname($sBranch);
                             }
                             $sBranchname=$oProject->getBranchname();
                             $aRepodata = $oProject->getRemoteBranches(true);
diff --git a/public_html/deployment/classes/vcs.git.class.php b/public_html/deployment/classes/vcs.git.class.php
index d361b364e4071507b2cec9b65ac115b92a399c76..d8d50f9872181d3faea4f85c93711d97f332ca85 100644
--- a/public_html/deployment/classes/vcs.git.class.php
+++ b/public_html/deployment/classes/vcs.git.class.php
@@ -102,6 +102,11 @@ class vcs implements iVcs {
         return $this->_aCfg = $aRepoConfig;
     }
 
+    /**
+     * set directory für current branch of a project below tempdir
+     * In it the branch will be initialized
+     * @return type
+     */
     private function _setTempdir() {
         $this->_sTempDir = $this->_aCfg["url"];
         $this->_sTempDir = preg_replace('/[\@\.\:\/]/', '_', $this->_sTempDir);
@@ -195,6 +200,7 @@ class vcs implements iVcs {
 
     /**
      * helper: cache hash with all branches
+     * It saves 1.5 sec for reading 300 branches
      * @return boolean
      */
     private function _cacheRemoteBranches() {
@@ -213,7 +219,7 @@ class vcs implements iVcs {
      * @return array
      */
     private function _fetchRemoteBranches($bForceNoCache = false) {
-        $this->log(__FUNCTION__." start");
+        $this->log(__FUNCTION__."(bForceNoCache = ".($bForceNoCache ? 'true' : 'false').") start");
         $aReturn = array();
 
         if (!$this->getUrl()) {
@@ -227,8 +233,10 @@ class vcs implements iVcs {
         // list of cached branch keys
         if ($oCache->isExpired() || $bForceNoCache) {
             $sWorkdir = dirname($this->_sTempDir) . '/fetchRemoteBranches/';
+            $this->log(__FUNCTION__." - sWorkdir = $sWorkdir");
             $sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
-            if (!file_exists($sWorkdir . ".git")) {
+
+            if (!is_dir($sWorkdir . ".git")) {
                 $sGitCmd.='mkdir -p "' . $sWorkdir . '" && cd "' . $sWorkdir . '" && ';
                 $sGitCmd.='git init >/dev/null && ';
                 $sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && ';
@@ -236,9 +244,9 @@ class vcs implements iVcs {
                 $sGitCmd.='cd "' . $sWorkdir . '" 2>&1 && ';
             }
             $sGitCmd.='git ls-remote --heads --tags origin 2>&1 ;';
-            $this->log(__FUNCTION__." start command $sGitCmd");
+            $this->log(__FUNCTION__." start command <code>$sGitCmd</code>");
             exec($sGitCmd, $aOutput, $iRc);
-            $this->log(__FUNCTION__." end with rc=$iRc ", ($iRc==0 ? 'info':'error'));
+            $this->log(__FUNCTION__." command ended with rc=$iRc ". '<pre>'.implode("\n", $aOutput).'</pre>', ($iRc==0 ? 'info':'error'));
             if ($iRc == 0) {
 
                 // use cache that getCommitmessageByBranch can access it
@@ -257,27 +265,27 @@ class vcs implements iVcs {
                     $this->log(__FUNCTION__ . ' loop over output of git ls-remote <pre>'.print_r($sBranchLine, 1).'</pre>');
                     $aTmp = explode("\t", $sBranchLine);
 
-                    $aBranch = explode("/", $aTmp[1]);
-                    $sBranch = array_pop($aBranch); // remove "refs"
+                    $sBranchPath = preg_replace('#^refs/#', '', $aTmp[1]);
+                    $sBranch = preg_replace('#^[a-z]*\/#', '', $sBranchPath);
 
                     // skip dereferences
                     // http://stackoverflow.com/questions/15472107/when-listing-git-ls-remote-why-theres-after-the-tag-name
                     if (!preg_match('/\^\{\}$/', $sBranch)) {
                         $sRevision = $aTmp[0];
-                        $sType = array_pop($aBranch);
+                        $sType   = preg_replace('#/.*$#',      '', $sBranchPath);
                         $sName = ($sType == "heads") ? "origin/" . $sBranch : $sBranch;
                         
                         $sBranchKey = $sName;
                         $this->log(__FUNCTION__ . ' $sBranchKey = '.$sBranchKey);
 
-                        $sMessage = $this->getCommitmessageByBranch($sName, $sRevision);
+                        // $sMessage = $this->getCommitmessageByBranch($sName, $sRevision);
                         $aReturn[$sBranchKey] = array(
                             // 'debug'=> $aTmp,
                             'revision' => $sRevision,
                             'name' => $sName,
                             'label' => $sType . ': ' . $sBranch,
                             'type' => $sType,
-                            'message' => $sMessage
+                            // 'message' => $sMessage
                         );
                     }
                 }
@@ -419,11 +427,11 @@ class vcs implements iVcs {
         }
 
         $sGitCmd.='git log -1 "' . $this->_sCurrentBranch . '" 2>&1 ; '; // 0.0 s
-        $this->log(__FUNCTION__." start command $sGitCmd");
+        $this->log(__FUNCTION__." start command <code>$sGitCmd</code>");
         // $sLoginfo = shell_exec($sGitCmd);
         exec($sGitCmd, $aOutput, $iRc);
+        $this->log(__FUNCTION__." command ended with rc=$iRc ". '<pre>'.implode("\n", $aOutput).'</pre>', ($iRc==0 ? 'info':'error'));
         $sLoginfo= implode("\n", $aOutput);
-        $this->log(__FUNCTION__." end with rc=$iRc <pre>$sLoginfo</pre>", ($iRc==0 ? 'info':'error'));
         
         /*
          * 
@@ -490,7 +498,7 @@ class vcs implements iVcs {
         $sBranchname = str_replace("origin/", "", $this->_sCurrentBranch);
 
         $sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
-        $sReturn=false;
+        $aOutput=false;
         $iRc=false;
         
         // this does not checkout tags in git v1.7 - only branches:
@@ -499,18 +507,18 @@ class vcs implements iVcs {
         // 
         $sGitCmd .= 'echo git clone "' . $this->getUrl() . '" "'.$sWorkDir.'" 2>&1 \&\& cd  "'.$sWorkDir.'" \&\& git checkout "' . $sBranchname . '" ; ';
         $sGitCmd .= '     git clone "' . $this->getUrl() . '" "'.$sWorkDir.'" 2>&1 &&   cd  "'.$sWorkDir.'" &&   git checkout "' . $sBranchname . '" 2>&1 ';
-        $this->log(__FUNCTION__." start command $sGitCmd");
+        $this->log(__FUNCTION__." start command <code>$sGitCmd</code>");
         // $sReturn = shell_exec($sGitCmd);
-        exec($sGitCmd, $sReturn, $iRc);
-        $this->log(__FUNCTION__." end command $sGitCmd");
-        return implode("\n", $sReturn). "\nrc=$iRc";
+        exec($sGitCmd, $aOutput, $iRc);
+        $this->log(__FUNCTION__." command ended with rc=$iRc ". '<pre>'.implode("\n", $aOutput).'</pre>', ($iRc==0 ? 'info':'error'));
+        return implode("\n", $aOutput). "\nrc=$iRc";
     }
 
     /**
      * return url to vcs sources
      */
     public function getUrl() {
-        $this->log(__FUNCTION__." start");
+        $this->log(__FUNCTION__." --> ".$this->_aCfg["url"]);
         return $this->_aCfg["url"];
     }
 
diff --git a/shellscripts/api-imlciserver.sh b/shellscripts/api-imlciserver.sh
index b61fe3f5c08b3aebb41a9e0b3d8726dc78d43ebb..d92f202be98c9e8a5a9b2c5020e13a874c410a07 100644
--- a/shellscripts/api-imlciserver.sh
+++ b/shellscripts/api-imlciserver.sh
@@ -4,8 +4,9 @@
 # API CLIENT :: API REQUEST TO IML CI SERVER
 #
 # ----------------------------------------------------------------------
-# 2020-07-23  v1.0  <axel.hahn@iml.unibe.ch> first lines
+# 2020-07-23  v1.0  <axel.hahn@iml.unibe.ch>  first lines
 # 2020-07-29  v1.1  <axel.hahn@iml.unibe.ch>  check "/" in branch; check http status 200 
+# 2021-03-29  v1.2  <axel.hahn@iml.unibe.ch>  support slashes in branch names
 # ======================================================================
 
 # ----------------------------------------------------------------------
@@ -146,7 +147,8 @@ echo "IMLCI_PROJECT = $IMLCI_PROJECT"
 echo "IMLCI_API_SECRET = $IMLCI_API_SECRET"
 echo
 
-echo $branch | grep '/.*/.*' >/dev/null && ( echo "WARNING: Do NOT use a branch containing a slash [/] in the name"; echo )
+# task-4364: slashes are supported now
+# echo $branch | grep '/.*/.*' >/dev/null && ( echo "WARNING: Do NOT use a branch containing a slash [/] in the name"; echo )
 
 
 echo ACTION: $apiAction