在第二期《开源世界大冒险 | 第 2 期:聊聊版本控制》中,我们对版本控制进行了讲解。Git 就是目前世界上最先进的分布式版本控制系统,它支持离线工作且高度自由,如今已成为了当代程序员必须要掌握的技能之一。
而它的诞生与 Linux 有着千丝万缕的关系。
Linux 之父 Linus Tovalds[1] 在 1991 年创建了开源的 Linux[2]。
随着 Linux 的发展,参与 Linux 的开发者也越来越多,开发者间的相互协作成了令人头疼的问题。
在 1991-2002 年期间,Linus 都在用手工合并的方式维护代码,提交补丁、保存归档等繁琐事务占据了内核维护工作的大量时间。
2002 年,Linus 决定使用 BitKeeper[3] 进行 Linux 的版本管理。
BitKeeper
BitKeeper 是一套闭源的商用分布式管理工具。使用闭源工具进行开源项目的代码管理,这个决定在 Linux 社区备受质疑和争议。
2005 年,一位 Linux 开发人员 Andrew 试图破解 BitKeeper 的协议,开发 BitKeeper 的商业公司 BitMover 认为他反编译了 BitKeeper,因此决定终止 Linux 免费使用 BitKeeper 的授权。
这一导火索迫使 Linux 开源社区,特别是 Linus 本人,开发一款属于自己的版本管理工具。
于是十天后,Git 诞生。
是的,你没有看错,Linus 仅用了两周时间就用 C 语言开发了一款分布式版本控制系统 —— Git。
「git」一词源自英国俚语,大致意思是「混账」。Linux 曾自嘲说:
I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git.(我是一个自负的混蛋,我以自己的名字命名所有的项目。先是 Linux,现在是 Git。)
2005 年,Git 以 GPL[4] 发布,它最初的目的仅仅是为了更好管理 Linux 内核代码。而后,Git 凭其优势迅速成为最流行的分布式版本控制系统。
Git 在各平台的安装方式各不相同,在这里就不多做介绍了,为大家提供各个平台的安装链接:
Git 本地数据管理,大概可以分为三个区:
.git
隐藏文件,这就是 Git 的版本库三大分区
使用 Git 进行版本控制的文件都处于以下四种状态之一:
commit
可以将修改同步到版本库文件的状态变化周期
想要熟练使用 Git 需要掌握很多命令,在这里先介绍一些日常工作中最常使用的命令。
在当前目录新建一个 Git 版本库:
$ git init
从远程克隆一个版本库:
$ git clone [project-url]
Git 的配置文件是 .gitconfig
。用户主目录下的 .gitconfig
为全局配置(global),项目目录下的 .gitconfig
则为项目配置。
设置提交代码时的用户信息:
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
显示当前 Git 配置:
$ git config --list
添加指定文件到暂存区:
$ git add [file1] [file2] ...
添加当前目录的所有文件到暂存区:
$ git add .
添加指定目录(包含子目录)到暂存区:
$ git add [dir]
删除工作区文件,并将删除操作同步到暂存区:
$ git rm [file1] [file2] ...
停止追踪文件:
$ git rm --cached [file]
修改文件名,该修改会被放入暂存区:
$ git mv [file-original] [file-renamed]
将暂存区文件同步到仓库区:
$ git commit -m [commit-message]
提交暂存区的指定文件:
$ git commit [file1] [file2] ... -m [commit-message]
列出所有本地分支:
$ git branch
列出所有远程分支:
$ git branch -r
列出本地分支和远程分支:
$ git branch -a
新建分支,但依旧停留在当前分支:
$ git branch [new-branch-name]
新建分支,且切换到新分支:
$ git branch -b [new-branch-name]
新建分支,并指向特定的 commit:
$ git branch [new-branch-name] [commit]
新建分支,并与远程分支建立追踪关系:
$ git branch --track [new-branch-name] [remote-branch]
切换到上一个分支:
$ git checkout -
切换到指定分支:
$ git checkout [branch-name]
合并指定分支到当前分支:
$ git merge [branch]
删除指定分支:
$ git branch -d [branch-name]
删除远程分支:
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
显示所有变更文件:
$ git status
显示当前分支版本历史:
$ git log
显示 commit 历史与每次 commit 时发生变更的文件:
$ git log --stat
根据关键词搜索提交记录:
$ git log -S [keyword]
显示某文件的历史版本:
$ git log --follow [file]
$ git watchanged [file]
显示过去 10 次提交:
$ git log -10 --pretty --oneline
显示暂存区与工作区的差异:
$ git diff
显示暂存区与上一次 commit 的差异:
$ git diff --cached [file]
显示工作区与当前分支最新 commit 之间的差异:
$ git diff HEAD
看看你今天写了多少代码:
$ git diff --shortstat "@{0 day ago}"
获取远程仓库的所有变动:
$ git fetch [remote]
获取远程仓库的所有变化,并与本地分支合并:
$ git pull [remote] [branch]
上传本地分支到远程仓库:
$ git push [remote] [branch]
强制推送当前分支到远程仓库:
$ git push [remote] --force
推送所有分支到远程仓库:
$ git push [remote] --all
恢复暂存区指定文件到工作区:
$ git checkout [file]
恢复暂存区所有文件到工作区:
$ git checkout .
重置暂存区的指定文件,让其与上一次 commit 保持一致:
$ git reset [file]
重置暂存区与工作区,与上一次 commit 保持一致:
$ git reset --hard
重置当前分支的 HEAD 为指定 commit,且重置暂存区,但工作区不变:
$ git reset [commit]
重置当前分支的 HEAD 为指定 commit,且重置暂存区和工作区,与指定 commit 一致:
$ git reset --hard [commit]
新建一个 commit,用来撤销指定 commit:
$ git revert [commit]
[1]
Linus Tovalds: https://en.wikipedia.org/wiki/Linus_Torvalds
[2]
Linux: https://zh.wikipedia.org/zh/Linux
[3]
BitKeeper: https://zh.wikipedia.org/wiki/BitKeeper
[4]
GPL: https://zh.wikipedia.org/wiki/GNU%E9%80%9A%E7%94%A8%E5%85%AC%E5%85%B1%E8%AE%B8%E5%8F%AF%E8%AF%81