wlxiong / git-sync

Use git for file synchronization: a toy project

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

git-sync
========

本项目使用 git 命令来实现文件同步, 该实现有如下特点:

1) 每个参与同步的设备都维护一个 git 库用来记录同步目录的修改, 默认只使用 master 一个分支.

2) 每个参与同步的设备通过 git 库中的远程分支 (refs/remotes/*) 来追踪其他设备的修改.
   假设有 HostA, HostB, HostC 三个设备, 那么在 HostA 维护的 git 库中有如下分支.

    $ git show-ref
    001724cbae16cfb822e94e4128f8892bc5ac41f9 refs/heads/master
    d7932d21c16a96eaa596e9ced8167ca0b978929f refs/remotes/HostB/master
    f579103238cb37d8858aed63fecc1f4d923ee698 refs/remotes/HostC/master

3) 如果某个设备对同步目录做了修改, 那么它会将这些修改 commit 到自己维护的 git 库的 master 分支上.
   但是该设备不会主动通知其他设备自己产生了新的修改.

4) 每个设备定时询问其他设备是否产生了新的修改. 在 (2) 中的例子里, 如果 HostA 询问 HostB 是否有新的修改时,
   会向 HostB 发出一条类似这样的请求 "SYNC d7932d21c16a96eaa596e9ced8167ca0b978929f". 请求中的 d7932d2
   告诉 HostB, HostA 已经拥有 HostB 上截止到 d7932d2 的所有修改.

5) 一个设备收到其他设备发来的 "SYNC <SHA1>" 请求时, 它会将 <SHA1>..<refs/heads/master> 之间的所有 commit
   导出到一个 *.bundle 文件中 (使用命令 git bundle create 生成), 并将该文件回复给发出请求的设备. 这样就实现了
   简单的增量同步.

6) 一个设备收到其他设备回复的 *.bundle 文件后, 它首先将该文件导入到本地的远程分支 (refs/remotes/*) 上,
   然后尝试将远程分支 merge 到自己的 git 库的 master 分支. 如果没有出现任何冲突, 那么这次同步就成功了.
   如果 merge 过程中出现冲突, 我们使用一个简单且易于实现的自动解决方法. 假设出现冲突的文件名为 my_file.txt,
   那么

   a) 将本地原有的 my_file.txt 文件重名为 my_file.version-<tag1>.txt, 其中 <tag1> 是使用命令 git hash-object
      获得的一个哈希值.
   b) 将取自 *.bundle 的 my_file.txt 文件重名为 my_file.version-<tag2>.txt, 其中 <tag2> 是使用命令 git hash-object
      获得的一个哈希值.
   c) 然后将 my_file.version-<tag1>.txt 和 my_file.version-<tag2>.txt 加入本地维护的 git 库中, 原来的 my_file.txt
      则从 git 库中删除.
   d) 使用 (a)-(c) 处理所有的冲突文件后, 对本地 git 库做 commit 操作, 于是本次同步结束.

   类似的策略使用在 git-annex 中, 参见链接
       http://git-annex.branchable.com/automatic_conflict_resolution/
       http://git-annex.branchable.com/design/assistant/blog/day_18__merging/


TODO List
=========

1) 删除较老的 commit 历史 (snapshot and cut history commits).
2) 文本文件: merge or not merge

About

Use git for file synchronization: a toy project


Languages

Language:Shell 100.0%