1

我已经尝试建立一种使用颠覆的合乎逻辑的方式(或任何其他 VCS,但我用 svn 玩得更多)。

让我从解释我的问题开始,我们是几个需要每天更改客户网站的同事,但是客户也可以通过他们在网站上的“管理面板”更改一些文件。以及在服务器上生成的一些文件、日志文件、导出/导入数据、站点地图等。

我们现在正在通过 FTP 工作,为了维护某种文件历史,我们制作了 .bak.revision#.php 文件,但它几乎无法管理。最重要的是,我使用 Netbeans 作为我的 IDE,这需要文件的本地副本。

要开始一个项目,我需要与我的客户同步更改的文件(或者最坏的情况下下载完整的项目)(这可能需要很长时间)。

我真的很喜欢使用 Netbeans,但现在我有时最终会改用 notepad++。

我设置了一个非常好的使用 SVN 的方式,它带有一个 post-commit 钩子,可以将项目导出到一个 http 文件夹中,这样我就可以对我的本地副本进行更新,进行更改,然后提交 -done-

但我不想覆盖服务器上可能已更改的文件,例如他们可以对自己进行更改的客户 CSS 文件。

所以我认为我不能是唯一一个遇到这个问题的人,如果不是团队中的每个人都这样做,如何使用 SVN?(在我的情况下是客户)

我猜我可以在那些文件上使用 svn:ignore 吗?

(这是测试环境) 我的 post commit hook 很简单;svn 导出文件:///svn/repo/LIVE /var/www/html/ --force


编辑我会研究的合理解决方案,如果我创建一个预提交,甚至更好?预更新?挂钩导入已经在仓库中的覆盖文件,这将解决我的问题,不是吗?

NVM Import 运行提交。提交和预提交不能很好地工作,因为它会创建一个无限循环


最诚挚的问候

4

4 回答 4

1

在您的情况下,最合乎逻辑和技术性的方式(但不是最简单的)将是

  • 将站点树转换为通用(使用您的 Netbeans)存储库的工作副本 - 这需要在服务器上安装 Subversion 和一些安装后技巧,因此:SSH root-access to host
  • 使用管理面板中的 crontab 作业|特殊按钮将现场直接更改提交到 repo
  • 更改提交后挂钩,在这种情况下,必须在从“外国”主机提交后更新服务器的 WC

更奇特的方式:颠覆所有人(对于某些用户 - 幕后)

  • 每个人都(直接)或间接使用 Subversion - 没有人在现场接触文件
  • 存储库中的更改(作为导出)存储在站点上,就像现在发生的那样

对于开发人员来说,这种方式不会改变任何事情。对于您建议的技术平庸的客户,准备和配置EasySVN(以及因此,Assembla 的存储库) - 他们只会获得本地文件夹(或树),其中所有更改(自动)与相关存储库同步(反向也可以工作 -从 repo 传递到 WC 的后台更新)。Assembla 空间的 SSH 或 FTP 工具将更改传输到站点(自动提交或手动按需)

于 2013-02-08T09:57:23.360 回答
1

您可以在网络服务器上本地使用 DVCS。与集中式 VCS 相比,分散式 VCS 将客户方面发生的事情与团队内部发生的事情分离。此外,这种情况是关于合并的,任何值得称道的 DVCS 都是关于合并,并且做得最好。

我在这里给出了一个使用 Git 的具体工作流程,但这对任何其他 DVCS 都是可行的。我将假设{TEAM}团队和网络服务器都可以访问一个存储库,以使这里的工作流程更简单,但是有多种方法可以做到这一点。您只是不能以更改文件的方式将您的开发团队直接推送到网络服务器的存储库,请参阅我对为什么您不能推送到 Git 中的已签出分支的解释。

网络服务器保存历史

在 中,您有一个主要分支,即TEAM/dev,您的开发发生在这里。您可以像这样创建网络服务器的存储库:

~$ git clone -b dev {TEAM} /var/www/mystuff
~$ cd /var/www/mystuff
mystuff$ git checkout -b locall-changes

在某些时候,您将提交网络服务器所做的任何事情。它可能是一项 cron 作业、一些 PHP 代码或手动干预:

mystuff$ git ci --all -m "Webserver modifications"

--all选项告诉 Git 提交对已被 Git 跟踪的文件的所有修改。如果网络服务器可能会创建您想要跟踪的新文件,您必须放置忽略模式(用于日志文件等)并以这种方式提交:

mystuff$ git add .
mystuff$ git ci -m "Webserver modifications"

此时请注意,自初始克隆以来,网络服务器和您的团队之间没有发生任何通信。这就是 DVCS 的优势:网络服务器的操作及其保存历史是完全自主的。您可能会破产或被核武器抹去,它不仅会继续工作,而且有人可以填补并无缝地继续您正在做的事情。

你与你的发展融为一体

您可以通过将其存储库设置为您身边的远程来跟踪网络服务器(您只需执行一次):

myrepo$ git remote add webserver ssh://webserver/var/www/mystuff
myrepo$ git fetch webserver
myrepo$ git branch changes webserver/local-changes

当您想将新代码发布到网络服务器时,您首先要获取它的历史记录并检查它是如何合并的:

myrepo$ git co changes
myrepo$ git pull

这将从远程网络服务器获取新提交并将更改分支更新为网络服务器上的本地更改

myrepo$ git merge dev

现在您检查合并是如何进行的,当您解决冲突并提交合并时,您可以在 {TEAM} 中使用它:

myrepo$ git push {TEAM} changes

回到网络服务器

一个网络服务器,你现在只需要拉那个合并。唯一的问题是,在此期间可能已经进行了一些新的提交。可以肯定的是,只有当您的合并是当前提交的直接后代时,您才能强制更新分支(Git 称之为快进合并):

mystuff$ git pull --ff-only {TEAM}/changes

如果没有 FF 是可能的,则此命令不会更改文件并以非零错误代码退出,这使得可以让自动脚本触发它并让您知道它是否真的发生。

于 2013-02-13T03:07:14.050 回答
0

:::我的发现:::

(@LazyBadger 这个答案太长了,无法发表评论。)

导出不起作用,我需要一个真正的工作目录。但是我可以直接在 httpd.conf 中拒绝访问,换句话说,.htaccess 文件没有任何麻烦。

我可以使用 UPDATE 在提交后脚本中使 web 目录保持最新。(下面的例子)

#!/bin/sh

REPOS="$1" REV="$2" cd /var/www/html/ 
MESSAGE=$(svnlook propget --revprop -r $REV $REPOS svn:log) 
Author=$(svnlook propget --revprop -r $REV $REPOS svn:author) 
CHANGES=$(svnlook changed -r $REV $REPOS)

echo "" >> /$REPOS/SVN.Log 
echo "Commit | $REPOS | $REV | $MESSAGE | $CHANGES | $Author" >> /$REPOS/SVN.Log 
echo update >> /$REPOS/SVN.Log 
svn update >> /$REPOS/SVN.Log 
echo klar >> /$REPOS/SVN.Log

为了使客户编辑的文件保持同步,我可以使用忽略(只是在存储库中没有这些文件),很可能用于二进制文件和日志文件,以控制存储库的大小。

然后我们可以使用提交守护进程来保持存储库最新,不幸的是,EasySVN 解决方案(顺便说一句很棒的软件,也是免费的,也可以与任何服务器一起使用)不适用于 Linux 环境(目前还没有)。

顺便说一句,EasySVN 可以轻松用于将文件备份到任何 SVN,并具有文件历史记录的巨大优势。小心!为了使用 svn+ssh 支持,您需要下载一个可以处理 -q 标志的 sshclient(例如来自这个包:http ://sharpsvn.open.collab.net/servlets/ProjectProcess?pageID=3794 )。并使用腻子中的选美

但是我可以偶尔使用 CRON 创建一个提交脚本或运行提交,它确实应该嵌入到 php 保存功能中,但这是一项主要工作,也许在我们软件的未来版本中它会:)

示例提交脚本:

#!/bin/sh
cd /var/www/html/ && svn commit -m webedit -q

那当然可以改进很多,例如我们可以先检查更改^^。

像脚本一样的示例守护程序,用于检查更改并在需要时提交

#!/bin/bash
SVNREPOS=( "/var/www/html/" )
cd /PATH/TO/THIS/SCRIPT/
LCK_FILE=`basename $0`.lck
if [ -f "${LCK_FILE}" ]; then
  echo LOCK exists
  MYPID=`head -n 1 $LCK_FILE`  

  if [ -n "`ps -p ${MYPID} | grep ${MYPID}`" ]; then
    echo `basename $0` is already running [$MYPID].
    exit
  else
    rm "${LCK_FILE}" -f
    sh $0
    exit
  fi

else
  echo $$ > $LCK_FILE
   while :; do
    for i in "${SVNREPOS[@]}"
     do
      cd $i
         #What are we doing here? Basicly we are testing if anything is to commit, if so commit it
         test ! $(svn st|wc -l) -eq 0 && svn ci -m SERVERCOMMIT -q 
      sleep 5s
     done
    done
echo ENDED LOOP IT SHOULD NOT HAVE DONE THAT
 rm "${LCK_FILE}" -f
 sh $0
fi

echo $$ > $LCK_FILE

用于启动/停止守护进程的 Init.d 脚本

#! /bin/bash
#SVN CHANGED MONITOR DAEMON
. /etc/init.d/functions

RETVAL=0
SCRIPTDAEMON=/PATHTO/changemonitor.sh
getpid() {
    pid=`ps -eo pid,command | grep "sh $SCRIPTDAEMON" | grep -v "grep" | awk '{ print $1 }'`
    }

start(){
    gprintf "Starting SVNChangeMonitor: "
    echo_failure
    getpid
    if [ -z "$pid" ]; then
      sh $SCRIPTDAEMON &
    fi

     getpid
     if [ -n "$pid" ]; then
         echo_success
     else
         echo_failure
     fi
    echo
    return $RETVAL
}

stop() {
    gprintf "Stopping SVNChangeMonitor: "
    echo_failure
    getpid
    if [ -n "$pid" ]; then
        kill -s kill $pid
        rm $SCRIPTDAEMON.lck -f

        getpid
         if [ -z "$pid" ]; then
             echo_success
         else
             echo_failure
         fi

    else
        echo_failure
    fi
    echo
    return $RETVAL
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        start
                gprintf "SVNChangeMonitor is restarted\n"
        ;;
  status)
        getpid
        if [ -n "$pid" ]; then
               gprintf "SVNChangeMonitor (pid %s) is running." "$pid"
               echo_success
                echo
        else
                RETVAL=1
                gprintf "SVNChangeMonitor is stopped\n"
                                echo
        fi
        ;;
  *)
        gprintf "Usage: %s {start|stop|restart|status}\n" "$0"
        echo
        exit 1
        ;;
esac

exit $RETVAL

感谢您的帮助和指点!

于 2013-02-12T22:42:22.130 回答
0

与其试图强迫客户使用 svn(有意或无意),不如将客户站点视为副本,并使用Unison之类的工具将非托管方(客户)与托管方(您的)保持一致。Unison 有点像 rsync,只是它处理双向的更改,因此客户更改的文件将被复制到您的系统中。

所以你的工作流程是:

  • 一致(将本地与远程同步;拉下他们的更改)
  • svn commit(检查他们的更改)
  • 编辑编辑编辑
  • svn commit(签入你的更改)
  • 一致(将遥控器与本地同步,也下拉任何他们可能有变化的东西)
于 2013-02-12T22:54:25.483 回答