如何同时使用Git和Dropbox?

gitDropbox可以一起使用吗?

311221 次浏览

我认为Dropbox上的Git很棒。我一直在使用它。我有多台电脑(两台在家,一台在工作),我在上面使用Dropbox作为中央裸存储库。由于我不想将它托管在公共服务上,而且我无法访问我可以随时SSH的服务器,Dropbox通过在后台同步来解决这个问题(非常快)。

安装程序是这样的:

~/project $ git init~/project $ git add .~/project $ git commit -m "first commit"~/project $ cd ~/Dropbox/git
~/Dropbox/git $ git init --bare project.git~/Dropbox/git $ cd ~/project
~/project $ git remote add origin ~/Dropbox/git/project.git~/project $ git push -u origin master

从那里,您只需克隆~/Dropbox/git/project.git目录(无论它属于您的Dropbox帐户还是在多个帐户之间共享)并执行所有正常的Git操作-它们将自动同步到您的所有其他机器。

我写了一篇博客文章“关于版本控制”,其中我介绍了我的环境设置背后的原因。它基于我的ruby on rails开发经验,但它可以应用于任何事情,真的。

我不认为使用Git和Dropbox是可行的方法……只要想想两者的功能:

Git:

  • 允许您拥有中央存储库
  • 允许您拥有自己的存储库和自己的更改
  • 允许您从中央存储库发送和接收更改
  • 允许多人更改相同的文件,他们合并它们,或者如果不能这样做,则要求您合并它们
  • 具有Web和桌面客户端以允许访问中央存储库

Dropbox:

  • 把所有东西都放在中央仓库里
  • 允许您在服务器中拥有自己的文件版本
  • 强制您从中央存储库发送和接收更改
  • 如果多人更改相同的文件,提交的第一个文件将被替换为以后的提交,并且不会发生合并,这很麻烦(绝对是它最大的缺点)
  • 具有Web和桌面客户端以允许访问中央存储库。

如果您担心共享一些文件,为什么不对它们进行加密?然后您可以将Dropbox到Git的最大优势,即拥有公共和私有文件……

我们在共享文件夹上使用这种方法(在Dropbox中创建一个裸存储库)。

一小部分开发人员可以从那个裸露的同步存储库中提取并创建一个本地克隆。一旦工作单元完成,我们就会推回到原点。

我缺少的一件事是,一旦发生推送到原点,就可以发送包含更改集信息的电子邮件。我们正在使用Google Wave手动跟踪更改。

我不想把我所有的项目都放在一个Git存储库下,也不想为每个项目运行这段代码,所以我做了一个Bash脚本来自动化这个过程。你可以在一个或多个目录上使用它-所以它可以为你做这篇文章中的代码,也可以一次在多个项目上做。

#!/bin/sh# Script by Eli Delventhal# Creates Git projects for file folders by making the origin Dropbox. You will need to install Dropbox for this to work.
# Not enough parameters, show help.if [ $# -lt 1 ] ; then
cat<<HELPprojects_to_git.sh -- Takes a project folder and creates a Git repository for it on Dropbox
USAGE:./projects_to_git.sh file1 file2 ..
EXAMPLES:./projects_to_git.sh path/to/MyProjectDirCreates a git project called MyProjectDir on Dropbox
./projects_to_git.sh path/to/workspace/*Creates a git project on Dropbox for every folder contained within the workspace directory, where the project name matches the folder name
HELPexit 0fi
# We have enough parameters, so let's actually do this thing.
START_DIR=$(pwd)
# Make sure we have a connection to Dropboxcd ~if [ -s 'Dropbox' ] ; thenecho "Found Dropbox directory."cd Dropboxif [ -s 'git' ] ; thenecho "    Dropbox Git directory found."elseecho "    Dropbox Git directory created."mkdir gitfielseecho "You do not have a Dropbox folder at ~/Dropbox! Install Dropbox. Aborting..."exit 0fi
# Process all directories matching the passed parameters.echo "Starting processing for all files..."for PROJ in $*doif [ -d $PROJ ] ; thenPROJNAME=$(basename $PROJ)echo "  Processing $PROJNAME..."
# Enable Git with this project.cd $PROJif [ -s '.git' ] ; thenecho "    $PROJNAME is already a Git repository, ignoring..."elseecho "    Initializing Git for $PROJNAME..."git init -qgit add .git commit -m "Initial creation of project." -q
# Make the origin Dropbox.
cd ~/Dropbox/gitif [ -s $PROJNAME ] ; thenecho "    Warning! $PROJNAME already exists in Git! Ignoring..."elseecho "    Putting $PROJNAME project on Dropbox..."mkdir $PROJNAMEcd $PROJNAMEgit init -q --barefi
# Link the project to the originecho "    Copying local $PROJNAME to Dropbox..."cd $PROJgit remote add origin "~/Dropbox/git/$PROJNAME"git push -q origin mastergit branch --set-upstream master origin/masterfifidone
echo "Done processing all files."cd $START_DIR

我将我的非Github存储库存储在Dropbox上。我遇到的一个警告是重新安装后同步。Dropbox会先下载最小的文件,然后再移动到较大的文件。如果你晚上开始,周末后回来,这不是问题:-)

我的主题-http://forums.dropbox.com/topic.php?id=29984&;回复=6

我喜欢丹·麦克内文的答案!我现在也在一起使用Git和Dropbox,我在.bash_profile中使用了几个别名,所以我的工作流程如下所示:

~/project $ git init~/project $ git add .~/project $ gcam "first commit"~/project $ git-dropbox

这些是我的别名:

alias gcam='git commit -a -m'alias gpom='git push origin master'alias gra='git remote add origin'alias git-dropbox='TMPGP=~/Dropbox/git/$(pwd | awk -F/ '\''{print $NF}'\'').git;mkdir -p $TMPGP && (cd $TMPGP; git init --bare) && gra $TMPGP && gpom'

我一直在以推荐的方式使用Mercurial,并敦促你保持谨慎,特别是如果任何一台机器有所不同。Dropbox论坛上充斥着关于自发出现的神秘文件名大小写问题的投诉。Hg(我假设是Git)在常规签入时不会注意到或抱怨,只有当你尝试真正使用它时,它抱怨存储库损坏时,你才会听到关于腐败的消息。坏消息。希望我能更具体地说明这个问题及其解决方法;我仍在努力自己从这个混乱中挖掘出来。

这个答案是基于Mercurial经验,而不是Git,但是这个经验表明,以这种方式使用Dropbox是在要求损坏的存储库,如果您有可能在不同时间从不同机器更新相同的基于Dropbox的存储库(Mac,Unix,在我的情况下是Windows)。

我没有一个完整的列表来列出可能出错的事情,但这里有一个让我感到不安的具体例子。每台机器都有自己的行尾字符概念,以及文件名中大小写字符的处理方式。Dropbox和Git/Mercurial处理这一点略有不同(我不记得确切的区别)。如果Dropbox背着Git/Mercurial更新存储库,那么很快就会发生,损坏的存储库。这会立即发生并且不可见,所以你甚至不知道你的存储库坏了,直到你尝试从中恢复一些东西。

用这种方式从一团糟的事情中挖掘出来后,我一直在使用以下食谱,取得了巨大的成功,没有任何问题的迹象。只需将您的存储库移出Dropbox。其他一切都使用Dropbox;留档,JAR文件,任何你喜欢的东西。并使用github(Git)或比特桶(Mercurial)来管理存储库本身。两者都是免费的,所以这不会增加成本,每个工具现在都发挥了自己的优势。

在Dropbox上运行Git/Mercurial除了风险之外没有任何增加。不要这样做。

还有一个开源项目(跨平台[Linux,Mac,Win]脚本的集合),它使用少量(3-4)命令来完成存储库管理的所有细节。

https://github.com/karalabe/gitbox/wiki

示例用法是:

$ gitbox create myappCreating empty repository...Initializing new repository...Repository successfully created.
$ gitbox clone myappCloning repository...Repository successfully cloned.

之后正常的git使用:

$ echo “Some change” > somefile.txt$ git add somefile.txt$ git commit –m “Created some file”$ git push

查看项目wiki和手册以获取完整的命令参考和教程。

我遇到过类似的问题,并为此创建了一个小脚本。我们的想法是尽可能简单地将Dropbox与Git一起使用。目前,我已经快速实现了ruby代码,我很快就会添加更多。

该脚本可在https://github.com/nuttylabs/box-git处访问。

对于使用Dropbox的小型团队:

如果每个开发人员在Dropbox上都有自己的可写裸存储库,这对其他开发人员来说是只拉,那么这有助于代码共享,而没有损坏的风险!

然后,如果您想要一个集中的“主线”,您可以让一个开发人员从他们自己的存储库管理所有推送。

我喜欢丹·麦克内文投票最多的答案。我最终做了太多次git命令序列,并决定制作一个脚本。所以这里是:

#!/bin/bash
# Usageusage() {echo "Usage: ${0} -m [ master-branch-directory ] -r [ remote-branch-directory ] [ project-name ]"exit 1}
# Defaultsdefaults() {masterdir="${HOME}/Dropbox/git"remotedir="${PWD}"gitignorefile="# OS generated files #\n\n.DS_Store\n.DS_Store?\n.Spotlight-V100\n.Trashes\nehthumbs.db\nThumbs.db"}
# Check if no argumentsif [ ${#} -eq 0 ] ; thenecho "Error: No arguments specified"usagefi
#Set defaultsdefaults
# Parse argumentswhile [ ${#} -ge 1 ]; docase "${1}" in'-h' | '--help' ) usage ;;'-m' )shiftmasterdir="${1}";;'-r' )shiftremotedir="${1}";;* )projectname="${1##*/}"projectname="${projectname%.git}.git";;esacshiftdone
# check if specified directories and project name existsif [ -z "${projectname}" ]; thenecho "Error: Project name not specified"usagefi
if [ ! -d "${remotedir}" ]; thenecho "Error: Remote directory ${remotedir} does not exist"usagefi
if [ ! -d "${masterdir}" ]; thenecho "Error: Master directory ${masterdir} does not exist"usagefi
#absolute pathsremotedir="`( cd \"${remotedir}\" && pwd )`"masterdir="`( cd \"${masterdir}\" && pwd )`"
#Make master git repositorycd "${masterdir}"git init --bare "${projectname}"
#make local repository and push to mastercd "${remotedir}"echo -e "${gitignorefile}" > .gitignore # default .gitignore filegit initgit add .git commit -m "first commit"git remote add origin "${masterdir}/${projectname}"git push -u origin master
#doneecho "----- Locations -----"echo "Remote branch location: ${remotedir}"echo "Master branch location: ${masterdir}"echo "Project Name: ${projectname}"

该脚本只需要一个项目名称。它将在~/Dropbox/git/中以指定的名称生成一个git存储库,并将当前目录的全部内容推送到新创建的原始主分支。如果给出多个项目名称,将使用最右边的项目名称参数。

可选地,-r命令参数指定将推送到源主机的远程分支。项目源主机的位置也可以使用-m参数指定。默认的. gitignore文件也放置在远程分支目录中。目录和. gitignore文件默认值在脚本中指定。

我使用Mercurial(或Git)+TrueCrypt+Dropbox加密远程备份

最酷的是,如果您修改一小部分代码,Dropbox不会同步整个TrueCrypt容器。同步时间大致与更改量成正比。即使它是加密的,TrueCrypt+Dropbox的组合也很好地利用了块密码+块级同步。

其次,单体加密容器不仅增加了安全性,还减少了存储库腐败的机会。

警告:但是,您必须非常小心,不要在Dropbox运行时安装容器。如果两个不同的客户端签入不同版本的容器,解决冲突也可能会很痛苦。因此,它仅适用于单个人使用它进行备份,而不适用于团队。

设置:

  • 创建一个Truecrypt容器(多千兆字节就可以了)
  • 在Truecrypt首选项下,取消选中preserve modification timestamp*。
  • 创建Dan(https://stackoverflow.com/a/1961515/781695)上面提到的存储库

用法:

  • 退出Dropbox
  • 挂载容器,推送更改,卸载
  • 运行Dropbox

附言:取消选中preserve modification timestamp会告诉dropbox文件已被修改并且应该同步。请注意,即使您没有更改其中的任何文件,挂载容器也会修改时间戳。如果您不希望发生这种情况,只需将卷挂载为read-only

现在在2014年,我已经使用Git和Dropbox大约一年半了,没有问题。注意事项:

  • 我所有使用Dropbox的机器都在Windows上,不同版本(7到8)+1个mac。
  • 我不与其他人共享存储库,因此我是唯一一个修改它的人。
  • git push推送到远程存储库,因此如果它损坏了,我可以轻松恢复它。
  • 我必须在C:\Usersmklink /D link target中创建别名,因为一些库指向绝对位置。

现在是2015年,截至三天前,已经创建了一个基于Dropbox API v2新工具来安全地在Dropbox上使用git。它可以针对API而不是使用桌面客户端工作,并正确处理多个同时推送到托管在共享文件夹中的存储库。

配置后,它允许设置一个与任何其他git远程完全相同的git远程。

git clone "dropbox::/path/to/repo"git remote add origin "dropbox::/path/to/repo"

正确的方法是使用git-Remote te-dropbox:https://github.com/anishathalye/git-remote-dropbox

在Dropbox中创建自己的裸仓库会导致很多问题。Anish(库的创建者)解释得最好

这些问题的根源在于Dropbox桌面客户端是为同步文件而设计的,而不是Git存储库。没有Git存储库的特殊处理,它不维护相同的保证为Git。远程存储库上的操作不再原子和并发操作或不幸的定时同步可能会导致存储库损坏。

传统的Git远程数据库在服务器端运行代码来完成这项工作”””正确的,但我们不能这样做。

解决方案:可以正确解决这个问题。可以使用Git与Dropbox具有相同的安全性和一致性保证作为传统的Git远程,即使有多个用户和

并行操作!

对于用户来说,这就像使用Git远程数据库一样简单作为Git和Git之间透明双向桥梁的助手Dropbox并维护传统Git远程的所有保证。它甚至可以安全地与共享文件夹一起使用,因此它可以用于协作(yay无限私人回购与无限合作伙伴!)。

使用远程助手,可以将Dropbox用作Git远程并继续使用所有常规的Git命令,如git clone、git拉取和git推送,一切都将按预期工作。

在不使用第三方集成工具的情况下,我可以稍微改善一下条件,并使用DropBox和其他类似的云盘服务,例如带有Git的SpiderOak。

目标是避免在这些文件修改中间进行同步,因为它可以上传部分状态,然后将其下载回来,完全破坏您的git状态。

为了避免这个问题,我做了:

  1. 使用git bundle create my_repo.git --all将我的git索引捆绑在一个文件中。
  2. 为文件监控设置延迟,例如5分钟,而不是瞬时。这减少了DropBox在更改过程中同步部分状态的机会。它在动态修改云盘上的文件时也有很大帮助(例如即时保存笔记应用程序)。

它并不完美,因为不能保证它不会再次弄乱git状态,但它有帮助,目前我没有遇到任何问题。

另一种方法:

到目前为止,所有的答案,包括最受欢迎的@阿丹回答,都解决了使用Dropbox集中共享存储库的想法,而不是使用专注于git的服务,如github、bit的等。

但是,由于原始问题没有说明“有效地使用Git和Dropbox”的真正含义,让我们使用另一种方法:“使用Dropbox仅同步工作树。”

操作方法有这些步骤:

  1. 在项目目录中,创建一个空的.git目录(例如mkdir -p myproject/.git

  2. 取消同步Dropbox中的.git目录。如果使用Dropbox应用程序:转到首选项、同步和“选择要同步的文件夹”,其中.git目录需要取消标记。这将删除.git目录。

  3. 在项目目录中运行git init

如果.git已经存在,它也可以工作,然后只执行步骤2。不过,Dropbox将在网站中保留git文件的副本。

第2步将导致Dropbox不同步git系统结构,这是此方法所需的结果。

为什么有人会使用这种方法?

  • 尚未推送的更改将有一个Dropbox备份,它们将跨设备同步。

  • 如果Dropbox在设备之间同步时搞砸了一些事情,git statusgit diff将很方便地解决问题。

  • 它节省了Dropbox帐户中的空间(整个历史记录不会存储在那里)

  • 它避免了@dubek和@Ates在对@Dan答案的评论中提出的担忧,以及@clu在另一个答案中提出的担忧

在其他地方(github等)存在远程将很好地使用这种方法。

在不同的分支上工作会带来一些问题,需要注意:

  • 一个潜在的问题是,当一个人签出不同的分支时,Dropbox(不必要?)可能会同步许多文件。

  • 如果两个或多个Dropbox同步设备签出了不同的分支,则可能会丢失对这两个设备的未提交更改。

解决这些问题的一种方法是使用#0将分支签出保存在单独的目录中。

对于我的2美分Dropbox只适用于个人使用,你不想麻烦获得中央存储库主机。对于任何专业开发,你可能会产生比你解决的更多的问题,正如在线程中已经提到过几次的那样,Dropbox不是为这个用例设计的。也就是说,在没有任何第三方插件或工具的情况下在Dropbox上转储存储库的一种完全安全的方法是使用捆绑包。我在.gitconfig中有以下别名来保存输入:

[alias]bundle-push = "!cd \"${GIT_PREFIX:-.}\" && if path=\"$(git config remote.\"$1\".url)\" && [ \"${path:0:1}\" = / ]; then git bundle create \"$path\" --all && git fetch \"$1\"; else echo \"Not a bundle remote\"; exit 1; fi #"bundle-fetch = "!cd \"${GIT_PREFIX:-.}\" && if path=\"$(git config remote.\"$1\".url)\" && [ \"${path:0:1}\" = / ]; then git bundle verify \"$path\" && git fetch \"$1\"; else echo \"Not a bundle remote\"; exit 1; fi #"bundle-new = "!cd \"${GIT_PREFIX:-.}\" && if [ -z \"${1:-}\" -o -z \"${2:-}\" ]; then echo \"Usage: git bundle-new <file> <remote name>\"; exit 1; elif [ -e \"$2\" ]; then echo \"File exist\"; exit 1; else git bundle create \"$2\" --all && git remote add -f \"$1\" \"$(realpath \"$2\")\"; fi #"

示例:

# Create bundle remote (in local repo)$ git bundle-new dropbox ~/Dropbox/my-repo.bundle# Fetch updates from dropbox$ git bundle-fetch dropbox# NOTE: writes over previous bundle. Thus, roughly equivalent to push --force --prune --all$ git bundle-push

在MacOS上,您也可以停止Dropbox,进行更改,然后重新启动Dropbox。我正在使用以下组合,并且非常满意:

在这两个(您的本地git托管项目目录和位于Dropbox上的远程git存储库)中运行以下命令以禁用自动打包(这是dropbox同步的主要问题)

git config --global gc.auto 0

然后不时地在禁用dropbox的情况下压缩存储库。例如,每当我发布新版本的应用程序时,我都会在我的bash-build脚本中执行以下操作。

osascript -e "tell application \"Dropbox\" to quit"
# Compress localgit gc --prune=now; git repack -a -d
# Compress remoteREPOS_DIR_REMOTE=`git remote get-url --push origin`cd "${REPOS_DIR_REMOTE}"git gc --prune=now; git repack -a -d
osascript -e "tell application \"Dropbox\" to launch"osascript -e "display notification with title \"Compress Done\""