Git学习笔记

创建版本库

1 初始化一个Git仓库:git init
2 添加文件到Git仓库,分两步:
第一步,git add <file>,可反复使用,也可一次添加多个文件。
第二部,git commit -m "commit description",完成。
3 掌握工作区的状态:git status
4 如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

时光机穿梭

版本回退

1 HEAD指向的版本就是当前版本,Git允许我们再版本的历史之间穿梭,使用命令:git reset --hard commit_id
(HEAD^为上一版本,HEAD^^为上上一版本,HEAD~100为往上100个版本)
2 要重返未来,用git reflog查看历史命令,以便确定要回到未来的哪个版本。

工作区和暂存区

Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
工作区(Working Directory) :就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区。
版本库(Repository) :工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。

我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

撤销修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

删除文件

在文件管理器中删除文件或者使用rm删除文件,如果确实要删除该文件,那就用命令git rm删掉,并且git commit。如果是删错了,则用git checkout -- test.txt把误删的文件恢复到最新版本。git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。(如果已经用git rm删除,则需要先使用git reset HEAD -- test.txt,然后再git checkout -- test.txt

远程仓库

本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,需要如下设置:
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,点“Add Key”,你就应该看到已经添加的Key。

添加远程库

要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;当使用GitHub时,server-name为github.com,path为GitHub用户名。
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步!

从远程库克隆

假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
1 登陆GitHub,创建一个新的仓库,名字叫gitskills。
2 用命令git clone克隆一个本地库。
git clone git@github.com:chinaeagle001/gitskills.git
GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。通过ssh支持的原生git协议速度最快。

分支管理

创建与合并分支

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上。
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变。

Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
创建+切换分支:git checkout -b <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>

解决冲突

合并两个分支时可能出现分支冲突的情况,需要手动解决冲突。
查看分支合并图:git log --graph --pretty=oneline --abbrev-commit
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

bug分支

当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。
查看工作现场:git stash list
恢复工作现场有两个办法:
一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了。

feature分支

开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

多人协作

查看远程库信息,使用git remote -v
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建。

标签管理

创建标签

命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id
git tag -a <tagname> -m "blablabla..."可以指定标签信息;
git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;
命令git tag可以查看所有标签。

删除标签

命令git push origin <tagname>可以推送一个本地标签;
命令git push origin --tags可以推送全部未推送过的本地标签
命令git tag -d <tagname>可以删除一个本地标签;
命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

GitHub

在GitHub上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送pull request给官方仓库来贡献代码。

其他设置

忽略特殊文件

忽略某些文件时,需要编写.gitignore
.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!
不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore

配置别名

将status别名设为st:git config --global alias.st status
配置一个git last,让其显示最后一次提交信息:git config --global alias.last 'log -1'

配置文件

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。每个仓库的Git配置文件都放在.git/config文件中。
当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中

参考资料:廖雪峰的官方网站-Git教程

上一篇:从Mysql slave system lock延迟说开去


下一篇:c++中基类与派生类中隐含的this指针的分析