如何将Git和Dropbox一起使用?

1136

2
请参阅Bradley Wright的教程 - Ron Romero
40
如果您只是一个小团队(我认为最多不超过5个人),那么BitBucket提供免费的私有代码仓库托管。具有讽刺意味的是,我会将本地代码仓库存储在Dropbox上,以防我在处理某些工作时需要在计算机之间切换。 - Mark Adamson
13
我不确定你所说的版本冗余是否具有讽刺意味,但它很可能非常有用。 - Silas Davis
3
这个问题不太清楚。使用这些工具“有效地”是什么意思?它也涉及范围过广,很可能会产生主观的答案。 - user456814
3
这个问题正在 meta 讨论:https://meta.stackoverflow.com/questions/401924/why-was-this-opinion-based-question-reopened#401924 - 10 Rep
显示剩余5条评论
20个回答

1406

我认为在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 操作 - 它们将自动同步到您的所有其他计算机中。

我写了一篇名为“On Version Control” 的博客文章,在其中介绍了我的环境设置背后的原因。它基于我的Ruby on Rails开发经验,但实际上可以适用于任何内容。


62
如果同时从两台计算机向Dropbox裸库提交,我想知道会发生什么。如果这导致Git内部文件的修改,Dropbox将显示冲突--那么你该怎么办呢?只需选择一个版本,然后从两台计算机(逐一)再次进行提交即可。 - dubek
165
你可能会破坏共享的裸仓库。这种方法只适用于小团队(我的情况下是两个人),人们可以隔着他们的隔板大喊:“嘿!别推了!我现在在推!” - Ates Goral
51
至少Git是分散式的,所以如果你设法破坏了东西,你可以从某个人的本地副本中恢复它。如果你有一个大团队,很可能有足够的资金在某个托管的代码仓库上。 - rdrey
7
我很确定这也是不安全的。通过SSH使用Git当然是安全的,但是Dropbox对并发和锁定没有任何保证,因此可能会丢失数据。由于您只是将其用作推拉操作的中心,所以应该没问题(我认为)-- 当出现问题时,您只需删除它并重新初始化即可。但是,使用SSH服务器来托管您的中心仓库有什么不好呢? - Jo Liss
15
使用裸仓库时,只同步Git元数据。如果您直接将本地代码仓库放入DropBox文件夹中,则每次切换不同分支时会有更多的DropBox流量,因为所有代码文件都会消失/出现/更改。这并不一定是问题,但它增加了关闭计算机之前(现在可能要更长时间)同步完成的风险,从而导致损坏问题。此外,裸仓库占用的空间较少,在DropBox免费空间仅为2GB(截至撰写本文时)的情况下,这是非常重要的。 - Holf
显示剩余24条评论

135
正确的方法是使用git-remote-dropbox:https://github.com/anishathalye/git-remote-dropbox 在Dropbox中创建自己的bare仓库会引起很多问题。该库的创建者Anish 最好地解释了这个问题:
“这些问题的根本原因是,Dropbox桌面客户端是为文件同步而设计的,而不是Git仓库。没有针对Git仓库的特殊处理,它不会保持与Git相同的担保。对远程仓库的操作不再是原子的,同时进行的操作或不幸的时间同步可能会导致损坏的仓库。
传统的Git remote在服务器端运行代码以使其正常工作,但我们无法做到这一点。
解决方案:可以正确地解决这个问题。可以使用Git和Dropbox,并且即使存在多个用户和并发操作,也具有传统Git远程的相同安全性和一致性保证!
对于用户,只需使用git-remote-dropbox,它是一个Git远程助手,充当Git和Dropbox之间透明的双向桥梁,并维护传统Git远程的所有保证。甚至可以与共享文件夹一起使用,因此可以用于协作(哎呀,无限制的私有仓库与无限制的合作者!)。
使用远程助手,可以将Dropbox用作Git远程,并继续使用所有常规Git命令,例如git clone、git pull和git push,一切都会如预期一样工作。

8
我很高兴看到有人在StackOverflow上发布了有关git-remote-dropbox的帖子。我想知道有没有办法让这个回复更接近顶部。目前被接受的答案推荐的方法相当危险,可能导致存储库损坏。 - fwenom
1
那真的很酷。我一定会去看看的。但是,当我从一个开发机器转移到另一个开发机器,并且想要继续在同步的存储库上工作时,只有在我离开机器A时总是提交我的工作并希望在机器B上继续工作时,这种方法才有效。我是对的吗?如果是这样,那就不理想了,因为它会导致一系列“临时”提交,这可能会污染存储库的提交历史记录。也许我只是不能两全其美! - bhu Boue vidya
1
@bhuBouevidya 不,那不是真的。您无需提交工作以进行同步更改。只要文件已保存,文件就会被同步。基本上,如果在一台机器上有许多修改过的文件,则修改将同步到另一台机器,因为Dropbox只关心已保存到磁盘的内容。 - shoke
2
@clu:是的,你必须提交并推送你的工作。git-remote-dropbox 所做的就是充当 git 远程助手。就像其他远程一样,本地提交只有在进行推送时才会被推送到远程。将本地修改的文件放入本地仓库以便推送的方法是进行提交。Dropbox 不会知道你的仓库之外的任何文件。 - Ants
2
只是好奇 git-remote-dropbox 是否跨平台...我看到它使用 Python,而且我知道某些其他用于 Dropbox 的 Python 工具跨平台,例如在 OS X 上命令行工具不兼容。 - Michael
基于这个已关闭的问题,我想是的。在Windows下使用Ruby在Jekyll中运行Python语法高亮器比这更痛苦。 - user4942583

91
这个答案基于Mercurial的经验,而不是Git,但这种经验表明,如果有可能在不同的机器上(在我的情况下为Mac、Unix、Windows)更新相同的基于Dropbox的存储库,则以这种方式使用Dropbox会导致损坏的存储库。
我没有列出所有可能出错的事情的完整清单,但这里有一个具体的例子。每台机器都有自己的行尾字符和文件名中大写/小写字符处理的概念。Dropbox 和 Git/Mercurial 处理这个问题略有不同(我不记得具体的区别)。如果 Dropbox 在 Git/Mercurial 没有注意到的情况下更新存储库,则存储库破裂。这会立即而又隐蔽地发生,因此在尝试从存储库中恢复某些内容之前,您甚至都不知道存储库已损坏。
从一堆这样的混乱中挣扎出来后,我一直在使用以下方法,并且非常成功,没有任何问题的迹象。简单地将存储库从 Dropbox 中移出。将 Dropbox 用于其他所有内容;文档、JAR 文件,任何您喜欢的东西。并使用GitHub(Git)或Bitbucket(Mercurial)来管理存储库本身。两者都是免费的,因此这不会增加任何成本,同时每个工具都可以发挥其优势。
在 Dropbox 之上运行 Git/Mercurial 没有任何好处,只会增加风险。不要这样做。

13
我认为 Git 仓库足够健壮,不会出现数据损坏。根据我的经验(使用了一年多,主要是单用户、跨平台、跨电脑和多开发者),Git 仓库很难被损坏。在 Git 中,只有信息被添加到仓库,现有文件99.9%的时间都不会被改动(可变文件大多容易手动检查)。我有时会看到分支指针被覆盖的情况,但这可以很容易地被发现(即“分支名(XXX 的冲突拷贝)”),并且可以被删除(实际上不需要真正的修复)。 - Egon
1
@tc:你说得对,在垃圾回收期间,git会删除非可达信息。然而,我认为在大多数实际情况下,这并不会影响鲁棒性:只有超过2周未被访问的不可达信息会受到影响(这对于DropBox同步来说已经足够充分)。而且在这种冲突发生的时候,我怀疑大部分信息都可以以打包和未打包的形式同时获取。 - Egon
我认为没有中央仓库的代码共享场景(在下面一个答案中描述的方式)可以避免因在dropbox目录中进行并发更新而导致的可能的损坏。如果需要中央仓库,可以将其单独管理(并且位于dropbox之外); dropbox将保存个人工作仓库(这也很方便,因为您可以从团队中某个人的源代码仓库定期更新/拉取,以此作为工作基础)。 (我实际上正在考虑在这种设置中使用darcs。) - imz -- Ivan Zakharyaschev
5
如果您不想公开托管您的代码库,可以使用Bitbucket,私有仓库对于多达5个用户的团队是免费的。请注意,私有仓库需要付费。 - Christian Specht
我注意到Windows机器和OSX机器之间的一个问题是文件权限可能会导致不同的问题。您可以使用以下命令在Git中关闭权限:"git config core.fileMode false"。 - devdrc

17

我不想把所有的项目都放在一个 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<<HELP
projects_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/MyProjectDir
        Creates 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

HELP
    exit 0
fi

# We have enough parameters, so let's actually do this thing.

START_DIR=$(pwd)

# Make sure we have a connection to Dropbox
cd ~
if [ -s 'Dropbox' ] ; then
    echo "Found Dropbox directory."
    cd Dropbox
    if [ -s 'git' ] ; then
        echo "    Dropbox Git directory found."
    else
        echo "    Dropbox Git directory created."
        mkdir git
    fi
else
    echo "You do not have a Dropbox folder at ~/Dropbox! Install Dropbox. Aborting..."
    exit 0
fi

# Process all directories matching the passed parameters.
echo "Starting processing for all files..."
for PROJ in $*
do
    if [ -d $PROJ ] ; then
        PROJNAME=$(basename $PROJ)
        echo "  Processing $PROJNAME..."

        # Enable Git with this project.
        cd $PROJ
        if [ -s '.git' ] ; then
            echo "    $PROJNAME is already a Git repository, ignoring..."
        else
            echo "    Initializing Git for $PROJNAME..."
            git init -q
            git add .
            git commit -m "Initial creation of project." -q

            # Make the origin Dropbox.

            cd ~/Dropbox/git
            if [ -s $PROJNAME ] ; then
                echo "    Warning! $PROJNAME already exists in Git! Ignoring..."
            else
                echo "    Putting $PROJNAME project on Dropbox..."
                mkdir $PROJNAME
                cd $PROJNAME
                git init -q --bare
            fi

            # Link the project to the origin
            echo "    Copying local $PROJNAME to Dropbox..."
            cd $PROJ
            git remote add origin "~/Dropbox/git/$PROJNAME"
            git push -q origin master
            git branch --set-upstream master origin/master
        fi
    fi
done

echo "Done processing all files."
cd $START_DIR

16

现在是2015年,就在三天前,基于Dropbox API v2新工具已经被创建出来,可以安全地在Dropbox上使用git。它与API交互而非使用桌面客户端,并正确处理托管在共享文件夹中的仓库的多个同时推送。

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

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

16

关于小团队使用Dropbox:

如果每个开发人员在Dropbox上拥有自己的可写裸库,并且其他开发人员只能进行拉取操作,则可以实现代码共享,而不会发生破坏的风险!

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


1
太棒了!此外,为了保护仓库免受多次写入的破坏,您可以轻松地创建多个仓库并仅同步它们的.git文件夹!您所需要的就是从所需的源拉取即可!伟大的点对点传输专家!您理解分散式Git的哲学! - Brian Cannard

15

我认为使用Git和Dropbox并不是一个好的选择……考虑一下它们各自的特点:

Git:

  • 允许你有一个中央代码库
  • 允许你拥有自己的代码库,并进行更改
  • 允许你与中央代码库交换更改
  • 允许多人更改同一文件并将它们合并,或者如果无法合并,则要求你自行合并
  • 提供网络和桌面客户端以访问中央代码库

Dropbox:

  • 将所有内容保存在中央存储库中
  • 允许你在服务器上拥有自己的文件版本
  • 强制你从中央存储库发送和接收更改
  • 如果多人更改同一文件,则先提交的文件将被后续的提交所替换,不会发生合并,这是令人烦恼的(也是其最大的缺点)
  • 提供网络和桌面客户端以访问中央存储库。

如果你担心共享某些文件,何不对它们进行加密呢?这样你就能同时享受到Dropbox和Git的最大优势,即拥有公共和私有文件……


Dropbox只是一个用于中央代码库的好选择。如果放置在共享文件夹中,它甚至可以为团队工作。 - mac
1
是的,但你不会像在git中那样拥有相同的合并功能。实际上,如果有人正在编辑与你相同的文件,并在你之后保存了该文件,除非你去Web界面下载旧版本(你的版本),否则你的更改将会丢失。 - Coyote21
8
这是错误的。Dropbox不会删除冲突文件。它会篡改一个编辑的文件名,并使用另一个以保持连续性。如果你愿意,你可以手动合并它们。这是一个很好的折中方案,不会丢失数据。http://www.dropbox.com/help/36 - Clueless
6
是的,但由于这是关于代码的问题,我花费在合并文件上的时间越少,我就能生产出更多的代码。在一个普通的代码库中,可能会一次出现数百个冲突,这取决于项目规模,如果要逐个合并它们,即使使用像WinMerge(或类似工具)这样的合并工具也会是一场噩梦。 - Coyote21

9
我使用Mercurial(或Git)+ TrueCrypt + Dropbox进行加密远程备份
最酷的事情是,如果您修改了代码的一小部分,则Dropbox不会同步整个TrueCrypt容器。同步时间大致与更改量成比例。即使它被加密,TrueCrypt + Dropbox的组合也很好地利用了块密码+块级同步。
其次,单片式加密容器不仅增加了安全性,还减少了存储库损坏的机会。 注意:但是,在运行Dropbox时不要挂载容器,否则必须非常小心。如果两个不同的客户端向容器检入不同版本,解决冲突也可能会很麻烦。因此,它只适用于单个人将其用作备份,而不适用于团队。
设置:

用法:

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

附:取消勾选保留修改时间戳告诉Dropbox文件已经被修改,应该同步。请注意,即使您没有在其中更改任何文件,挂载容器也会修改时间戳。如果您不希望发生这种情况,请将卷挂载为只读


如果使用MacOS加密的.dmg文件映像,会有很大的不同吗?同步时间是否仍然与更改大致成比例? - IBrum
@IBrum 抱歉,我还没有尝试过使用 .dmg 文件。 - user

7

我喜欢Dan McNevin的答案!我现在也在同时使用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'

我可能不会使用“last thing”作为别名,而是使用一个shell脚本。否则,我非常喜欢这个。如果使用awk的话,可以额外加分。 - pauljohn32

7
我们在Dropbox上的共享文件夹中使用这种方法(创建裸仓库)。小组开发者可以从这个同步的裸仓库拉取并创建本地克隆。完成工作后,我们将更改推送回原始仓库。唯一不足之处是缺乏通知机制,在更改推送到原始仓库时无法自动发送电子邮件通知。我们目前使用Google Wave手动跟踪变更信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接