GIT太难了
确实很难
GIT学起来费劲, 解释起来麻烦.
从2008看Linus在Google的GIT演技这个演讲就开始了.
我从头到尾读过 Pro Git, Git from button up. 看过几乎所有文档, 很了解什么是blob, tree, sha1...给各式各样的团队分享过git的原理和使用.
我发现我依旧被叫去解决各种各样, 一言难尽的问题.
"别人的push冲掉了我的提交, 怎么办?"
没有人能冲掉你的commit, 你们的远端是receive.denyNonFastForwards = true的. fast forward的意思是这样的, 我给你画个图...
"我怎么删除一个分支?"
随意删就好了呀, 哦, 你只删除本地是不行的, 每次pull的时候都会重建, 你是想删除本地分支(local branch)还是远程分支? 还是所有的远程跟踪分支(remote tracking branch)
"我推错了代码, 怎么能回滚回来呀, 我不想让别人看到????"
开始我觉得这些问题很菜鸡, 他们不看文档, 不学习, 不了解x,y,z...
但是, 作为一个版本管理工具, 非得让一个想急于上传自己的工作到代码库的用户, 思路转到他在操作一个有向图, 是不是有点过分?
从技术层面, github的规模和成功是git强大的证明, Linus的技术能力毋庸置疑. GIT是linux内核团队自用的代码管理工具. 设计理念是不可变的数据结构, 分布式的本地库, Linus本人最初的用法是直接读写blob tree, 他可能连push/pull都不需要.
但是, 作为日常版本管理工具, GIT的要求会不会有点多? 好比说我要上网看个视频, 有人塞给我一个编译器, 说"齐活了, 自己撸一个浏览器吧...".
用户对于版本管理是有直观理解的: 我做了些改动, 我要把我的改动推到库里, 团队其他成员可以帮我review以下, 在此基础上继续改动, 知道我们通过测试, 发布版本.
这个似乎很简单的过程一旦编程命令行, 和git的工作流, 就会突然遇到障碍, 需要以月或者年计的时间来熟悉掌握最终达到深入理解, 而且形成完善的工作流.
在这个阶段GUI是有价值的, 并不是像某些人说的那样, 精通GIT的人都会选择命令行.
新一代程用户来自于完全不同的背景, 他们不是内核维护者, 不是命令行熟练用户, 甚至都不是程序员, 谁说写小说的, 画画的就不需要版本管理?
本文不是对GIT的吐槽, 我也不想重复GIT本质上很简单的陈词滥调, GIT本可以更易用.
难在何处
难在git的一些定义是反直觉的概念定义
- commit不单单是提交, 也对应它被创造时的整个文件世界.
- commit的内容既是快照又是补丁.
- remote定义模糊且时间滞后.
- branch不是直观意义上的代码分支,它们更像是书签.
- 合并冲突确实很困难(不论用什么客户端工具).
- pull的存在加剧了理解的困难, fetch 和 merge/rebase应该分开..
commit不单单是提交
提交(Commit)在Git中是唯一且不可变的,它包含内容和上下文两个部分。换句话说,提交不仅仅是代码的快照,还包括了这些代码是如何达到当前状态的全部路径。这种理解对于Git新手来说可能并不容易,而对于不熟悉这一模型的人来说,容易引发问题.
commit的内容既是快照又是补丁
如果checkout某个commit, commit对应为磁盘上的快照, 但Git某些操作会将其视为一系列的变更(补丁)。例如,cherry-pick 或 revert 这类命令会将提交视为一个补丁来处理.
remote定义模糊且时间滞后
在使用Git时,实际上可能会接触到多个"版本"的仓库:本地仓库、网络上的上游远程仓库,以及上一次获取操作后缓存在本地的远程仓库分支。这些容易让新手混淆.
branch不是直观意义上的代码分支,它们更像是书签
在Git中,分支更像是可以快速切换的书签。它们并不相互排斥,也不“拥有”它们所在的历史分支.
合并冲突确实很困难(不论用什么代客户端)
合并冲突并不是概念上的问题,而是在解析和解决冲突时会遇到的实际困难.
pull的存在加剧了理解的困难, fetch 和 merge/rebase应该分开
该命令会直接改变本地分支以包含上游的更改,这对于新手来说可能会导致一系列问题。
建议教导新手使用更基础的 "fetch, observe, then consciously choose whether to fast-forward / do a merge commit / rebase / reset" 工作流程,而不是依赖 git pull.
结论
所以, 不要有挫败感(Don't Panic). 在有更好抽象的版本工具诞生之前, 好好学习GIT吧. 理解背后的原理, 熟悉使用更好的客户端工具(最好的客户端是emacs的magit).
让我们期待代码管理器更好的明天.