再次安利一下 Git 的创始人(也是 Linux 的创始人) Linus Torvalds 的这个 TED,Linus Torvalds 的意思是自己是为了专心一个人工作才创造的 Git:
https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux
越多的人参与到非零和游戏中的时候,往往会让利益得到稳定而持续的发展,过程中的重复博弈会催生合作的行为并最终发展成为文化和传统,学术体系、市场经济、维基百科、乃至整个互联网,都是如此,而以 Git 为基础的 Github,也在延续着这样的发展规律,让上千万的程序员的合作,成为可能
Git 在我看来是一种“自组织的垄断产生”,在技术的世界非常的普遍,当一种竞争的环境中出现了一种太过于优秀的物种,那么暂时性的垄断便会形成,“自组织的垄断产生”和传统垄断最主要的差别是,“自组织的垄断产生”在主观上并不追求垄断,但是会造成事实上的垄断,“市场和垄断”,我觉得在互联网时代,有非常多的新的可研究元素
同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用分布式版本控制系统 BitKeeper 来管理和维护代码。
到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds )不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。他们对新的系统制订了若干目标:
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许上千个并行开发的分支)
- 完全分布式
- 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,它还有着令人难以置信的非线性分支管理系统,可以应付各种复杂的项目开发需求。
Git 官网:
https://git-scm.com/
目前的最新版本是 v2.1
基本操作
在 Github 创建好项目以后会提供一个这样的地址:
[email protected]:samon127/clownfish.git
在本地创建一个库:
git clone [email protected]:samon127/clownfish.git .
clone 的时候如果遇到错误
git clone [email protected]:samon127/clownfish.git .
Cloning into 'clownfish'...
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
需要在本地生成一个 ssh key 然后添加到 github 里面,解决方法很简单,具体可以参考:
http://stackoverflow.com/questions/2643502/git-permission-denied-publickey
新建文件以后添加到库里面(最后一个参数 . 表示从 git 的根目录开始,而不是当前目录):
git add .
将这个新建的文件提交到本地的库里面:
git commit -m 'commit content'
如果不小心错误的 commit 了文件,退回也很简单
// 找到你需要回退到的哈希值,比如:72541c0ce9e7bd647ab9875641160deae543ab13
git log
// 进行回退操作
git reset --hard 72541c0ce9e7bd647ab9875641160deae543ab13
最后把这个新库的内容推送到服务器上面:
git push origin master
如果需要在推送之前查看一下做了哪些修改:
git diff
更新一个目录:
git pull
删除一个文件:
git rm file.txt
取消一个文件的所有修改:
git checkout test.php
回滚:
git reset --hard d4556882
git push origin HEAD --force
处理冲突
如果希望保留生产服务器上所做的改动,仅仅并入新配置项,处理方法如下:
git stash
git pull
git stash pop
然后可以使用Git diff -w <文件名> 来确认代码自动合并的情况
如果希望用代码库中的文件完全覆盖本地工作版本。方法如下:
git reset --hard
git pull
如果你希望覆盖的更为彻底,完全忽略本地的修改历史,则可以是:
git reset --hard origin/master
如果是手动处理的冲突,那么接下来的操作也很简单:
git add .
git commit -m 'fix conflicts'
.gitignore 相关:
.gitignore 是管理需要忽略的文件,不需要上传到 git 库中
- 以“#”开头表示注释;
- 以“/”开头表示目录;
- 以“*”通配多个字符;
- 以“?”通配单个字符;
- 以“[]”包含单个字符的匹配列表;
- 以“!”表示不忽略(跟踪)匹配到的文件或目录;
有优先级,后面的会覆盖前面,比如:
* !.gitignore
我目前的 .gitignore 内容为:
####################################
######## OS generated files ########
####################################
.DS_Store
.DS_Store?
*.swp
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
####################################
############# laravel5 ##############
####################################
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
/.idea
/.vagrant
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.env
####################################
############# un42 ##############
####################################
highlight.js
[0-9]*.js
/public/**/*.map
/public/js/highlight.js
/yarn.lock
composer.lock
package-lock.json
.editorconfig
*.sublime-workspace
*.sublime-project
.tags
.tags_sorted_by_file
public/*.node
钩子
在 .git/hooks 目录下面有一些 hooks 文件,里面存放了一些钩子的示例,但是 git 支持的钩子并不止这些
官方文档:
https://www.kernel.org/pub/software/scm/git/docs/githooks.html
applypatch-msg, pre-applypatch 和 post-applypatch 三个钩子会被 git am 的时候调用(一般现在不大会遇到通过邮件来提交代码了)
pre-commit, post-commit, prepare-commit-msg, commit-msg 会在执行 git commit 的时候被调用,和执行 commit 提交相关的操作相关
pre-rebase 这个钩子和 git rebase(让分支基于新的主干开始工作) 命令相关联,在 branch 上 rebase 一些 commit 的过程中触发
post-checkout 这个钩子在执行 git checkout(创建和切换分支) 命令的时候会触发
post-merge 在运行 git merge(获取和合并主干上的最新提交) 命令时会被触发,而git merge 也会在 git pull 命令后自动触发,因此可以用在更新代码之后的自动化操作
pre-push 在运行 git push 命令的时候会被触发
pre-receive, update, post-receive, post-update, push-to-checkout 这五个是在运行 git-receive-pack 命令被调用的时候,一般和使用者关系不大,属于资源库这端的一些相关处理
pre-auto-gc 在运行 git gc --auto(自动清理不需要的文件和对资源库进行优化) 命令的时候被调用
post-rewrite 在运行 git commit --amend, git-rebase 命令的时候会调用到的钩子