介绍

团队从 SVN 迁移到 Git LFS 后,使用 Git 进行协作时,遇到了很多问题:

  • 团队人员之前并没有使用 Git 的经验,导致所有成员都需要学习过渡适应。
  • SVN 与 Git 的心智模型不一致也产生了许多问题,典型的如 SVN 可以进行部分更新、部分提交,而 Git 则将整个仓库看作一个整体,只能整体更新或整体提交导致协作不便。
  • Git GUI 软件成熟度不够,导致进行某些操作(拉取、变基等等)时出现了文件丢失现象。

学习

首先介绍拉取、提交、推送这些核心概念。有兴趣的人推荐下面的资料进行学习。

心智模型

由于 Git 是分布式版本控制系统,也就是说本质上允许本地进行提交。

而 SVN 进行提交时必须通过服务器。

这个区别是在使用时容易产生最大问题的地方。

关键问题

Git 提交如果想要推送到远程,必须是远程可以通过 fast-forward 方式合并的提交。

这时这些提交产生了几种不同的处理方式,git pull 的提示信息中也给出了提示:

1
2
3
4
5
6
7
8
$ git pull
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

  git config pull.rebase false  # merge (the default strategy)
  git config pull.rebase true   # rebase
  git config pull.ff only       # fast-forward only

实践中可以使用的方法:

  1. 拉取的时候使用默认的合并策略,即每次都生成一个最新的合并提交,然后再推送。这种方式会导致提交被“加塞”后多出一个合并提交。大部分人与团队都会使用这个默认的策略,导致项目的提交历史充斥着大量自动产生的无用合并提交。具体信息参考:Git 干净的历史 - 狂飙
  2. 拉取的时候使用变基策略,同时配合 rebase.autostash true 将本地未提交的文件储存,但是实际使用时由于 Windows 系统限制,文件被应用程序打开时会被占用,导致无法移动位置或删除修改。
  3. 拉取的时候使用只允许 fast-forward 策略,这样要求用户自己在拉取失败时手动回滚提交,再拉取更新、提交、推送,导致整个操作变得复杂起来。

软件成熟度

虽然经过几年的发展,Git GUI 软件数量变得多了起来,可是质量参差不齐,令人难受。

Sourcetree

虽然是一个较早的软件(2013 年就发布了 Windows 版本),但是存在很多问题:打开仓库慢、显示提交慢、界面操作反应慢。本身是使用 .Net Framework 编写的 GUI 程序,但是效率不佳。

Fork

作为同样使用 .Net Framework 编写的 GUI 程序,Fork 的速度要比 Sourcetree 快很多,不管是操作、显示历史都要快。

Fork 不是完美的,本身存在着大量功能缺失。

现在使用的版本是 Windows v1.53.2.0,发现的问题如下:

  • 勾选 Rebase 拉取后文件没有正确放置在 stage 区域
  • 无法显示 当前文件与 stage 的区别 stage 与提交的区别
  • 无法查看 LFS 文件差异
  • 没有文件搜索功能
  • 头像无法像macOS显示姓
  • 输入框的提交信息记录历史表现很奇怪,撤销提交后记录消失

服务器设置

设置 Git 钩子,检查错误合并提交、作者信息、误提交文件。

将脚本放在 GitLab 的一个仓库中,修改 post-receive.sh 将自己作为当前仓库的勾子更新目标仓库。

客户端设置

初始化仓库状态、设置 Git 选项。

  • setup.sh 使用变基方式拉取更新
  • setup2.sh 使用快进式方式拉取更新,拉取更新失败时使用 rollback.sh 回滚本地提交后再拉取更新、提交、推送。

将脚本放在项目根目录,第一次克隆仓库后执行 setup 脚本初始化。