首页 > 代码库 > 我的git与github学习历程

我的git与github学习历程

因为想要知道如何把代码放到github上,所以就百度了一下,然后找到一个《如何从github上面拷贝源码》的文章,就先进行练习了下
 
1.首先到git官网下载git版本控制工具的安装包,下载好双击安装,所有的步骤我都默认的。
git官网:http://git-scm.com/download/
技术分享

 

技术分享

 

技术分享

 

2.然后安装完成我把没打勾的地方都打勾了,然后点击完成就出现如下图蓝色网页和黑色弹框,蓝色网页的网址: file:///D:/Program%20Files/Git/ReleaseNotes.html
技术分享

技术分享

 

看到这些的时候我都不知道该怎么操作
 
然后百度了下git教程
找到一个 廖雪峰的教程 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/
 
根据教程学习
创建版本库(即仓库)
可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
d命令用于显示当前目录。在我的电脑上,这个仓库位于。通过命令把这个目录变成Git可以管理的仓库
下面是创建版本仓库的步骤:
技术分享
在learngit目录下(子目录也可以)创建一个readme.txt文件。内容随便。
然后使用命令 git add readme.txt 把文件添加到仓库,执行之后没有任何显示就对了,然后使用命令 git commit -m "my first commit" 把文件提交到仓库 -m后面是本次提交的说明,可以是任意内容。可以帮助你从历史纪录里找到改动记录
 
git add命令可以多次使用
 
成功添加并提交readme.txt文件之后,我们将readme.txt文件的内容修改下,然后使用git status(可以查看仓库当前的状态)命令看下结果,结果如下:技术分享
结果告诉我们readme.txt被修改过但还没有准备提交。我们可以使用 git diff这个命令查看修改了什么内容
技术分享
从图中可以看出我们将红字中的four改成了绿色文字中的six。知道对readme.txt文件做了什么修改后,就可以放心提交到仓库了。提交修改和提交新文件是一样的两步。
 
如果我们不想要最新修改的文件,想要回到之前的版本。我们可以先使用 git log 查看版本修改的历史纪录
技术分享
git log 命令显示从最近到最远的提交日志,如果觉得输出信息太多,可以使用 git log --pretty=oneline
 
需要友情提示的是,你看到的一大串类似的是(版本号),和SVN不一样,Git的不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的和我的肯定不一样,以你自己的为准。为什么需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
 
使用git log命令之后我们就知道我们有哪些版本记录了,然后我们将readme.txt回退到上一个版本。在Git中,用HEAD表示当前版本,也就是最新的版本,上一个版本是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较多,所以写成现在使用命令将readme.txt回退到上一个版本: 
技术分享
 
然后使用git log 查看版本库的状态,最新的版本已经看不到了。
技术分享
如果我们还想回到最新的版本怎么做呢?我们只要知道最新版的版本号就可以了。然后使用
git reset --hard 版本号前几位 就可以回到未来的某个版本
技术分享
cat readme.txt查看readme.txt的内容 已经回到了最新版本
技术分享

 

但是如果你已经关闭了git的命令窗口,不能往回查看版本号了,怎么办呢?我们还有一个命令可以查看commit id 就是git reflog命令,它记录了你的每一次命令。

总结:
1.HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令 git reset --hard commit_id。
2.穿梭前,用git log 可以查看提交历史,以便确定要回退到哪个版本。
3.要重返未来,用git reflog 查看命令历史,以便确定要回到未来的哪个版本。


学到版本回退时不知道怎么进入git仓库,问了下同学写如下命令即可 cd 后面是git仓库的路径,如果忘记git仓库的路径,可以使用pwd命令查看路径

技术分享

工作区和暂存区
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用提交更改,实际上就是把暂存区的所有内容提交到当前分支。
 
先实践一下:先对readme.txt做个修改,然后在工作区添加一个LICENSE文本文件,内容随便写
 
然后使用git status命令查看下状态
技术分享
Git非常清楚地告诉我们,readme.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked。

现在,使用两次命令git add,把readme.txt和LICENSE都添加后,用git status再查看一下:

技术分享

现在所有的文件都放到了暂存区了,然后执行git commit 就可以一次性把暂存区的所有修改都提交到分支。技术分享
一旦提交后,如果你对工作区没有任何修改,那么工作区就是干净的。
技术分享

管理修改
了解Git是如何跟踪修改的,每次修改,如果不add到暂存区,那就不会加入到commit中。

撤销修改
小结
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。

技术分享

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

删除文件
新建一个test文件,内容随便,然后添加到Git并提交
如果在工作区将test文件删掉了或者使用rm命令删了,git status会告诉你哪些文件删了

技术分享

如果确实要删除就使用git rm命令并且git commit
技术分享

技术分享

如果删错了,想要恢复就使用git checkout
技术分享

 

远程仓库
github就是一个免费的远程仓库,不过需要先注册哦!
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

这个是一路回车什么都没设置的
技术分享

如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:

技术分享

 

 
点击add SSH key
技术分享

添加远程库
现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。
首先,登陆GitHub,然后,在右上角找到“New repository”按钮,创建一个新的仓库,只需要填写Repository name,其他默认即可,我这里填的learngit

技术分享

点击create repository,就成功创建了一个新的git 仓库
技术分享
 

目前,在GitHub上的这个learngit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
现在,我们根据GitHub的提示,在本地的learngit仓库下运行命令:

技术分享

请千万注意,把上面的luojiao123替换成你自己的GitHub账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key公钥不在我的账户列表中。
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

下一步,就可以把本地库的所有内容推送到远程库上:
技术分享

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样:

技术分享

 

 

从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master

把本地master分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!

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


从远程库克隆
上次我们讲了先有本地库,后有远程库的时候,如何关联远程库。
现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
首先,登陆GitHub,创建一个新的仓库,名字叫gitskills:

技术分享

 

 我们勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件:
 
技术分享

现在,远程库已经准备好了,下一步是用命令git clone克隆一个本地库:

技术分享

 

 

然后到本地git目录查看gitskills文件里面已经有readme.txt文件了
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
你也许还注意到,GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。

创建与合并分支
创建dev分支,然后切换到dev分支

技术分享

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev

然后使用git branch命令查看当前分支

技术分享

git branch命令会列出所有分支,当前分支前面会标一个*号。
然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,加上一行:
Creating a new branch is quick.
然后提交

技术分享

现在dev分支完成,我们就可以切换回master分支
技术分享

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
现在,我们把dev分支的工作成果合并到master分支上:

技术分享

git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward
合并完成后,就可以放心地删除dev分支了:

技术分享

删除后,查看branch,就只剩下master分支了:
技术分享

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

解决分支合并的冲突
准备新的feature1分支,继续我们的新分支开发:

技术分享

修改readme.txt最后一行,改为:
Creating a new branch is quick AND simple.

在feature1分支上提交:

技术分享

切换到master分支
技术分享

Git还会自动提示我们当前master分支比远程的master分支要超前1个提交。
在master分支上把readme.txt文件的最后一行改为:
Creating a new branch is quick & simple.
提交

技术分享

这时主分支和featurel分支修改的内容不一致,有冲突,当我们合并的时候就合并不了。

技术分享

Git告诉我们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:

技术分享

我们可以直接查看readme.txt的内容,里面有冲突的显示,我们修改如下后保存:
Creating a new branch is quick and simple.

再提交:

技术分享

用带参数的git log也可以看到分支的合并情况 --graph查看分支合并图:

技术分享

最后,删除feature1分支:

技术分享

工作完成。

分支管理策略
合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
下面我们实战一下--no-ff方式的git merge:
首先,仍然创建并切换dev分支:

技术分享

修改readme.txt文件,然后提交一个新的commit

技术分享

 

现在我们切换回master
技术分享
 
准备合并dev分支,请注意--no-ff参数,表示禁用Fast forward:
 技术分享

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
合并后,我们用git log看看分支历史:

技术分享

多人协作
使用git remote显示详细信息,我的gitskils文件夹里的git仓库是连接远程github的

技术分享

推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
技术分享
 
如果要推送其他分支,比如dev,就写成
技术分享

但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
● master分支是主分支,因此要时刻与远程同步;
● dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
● bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
● feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!

抓取分支
多人协作时,大家都会往master和dev分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:

技术分享

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

在Git中打标签非常简单,首先,切换到需要打标签的分支上:
$ git branch
* dev
master
$ git checkout master
Switched to branch ‘master‘

然后,敲命令git tag <name>就可以打一个新标签:
$ git tag v1.0

可以用命令git tag查看所有标签:
$ git tag
v1.0

默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?
方法是找到历史提交的commit id,然后打上就可以了:
$ git log --pretty=oneline --abbrev-commit
6a5819e merged bug fix 101
cc17032 fix bug 101
7825a50 merge with no-ff
6224937 add merge
59bc1cb conflict fixed
400b400 & simple
75a857c AND simple
fec145a branch test
d17efd8 remove test.txt
...

比方说要对add merge这次提交打标签,它对应的commit id是6224937,敲入命令:
$ git tag v0.9 6224937

再用命令git tag查看标签:
$ git tag
v0.9
v1.0

注意,标签不是按时间顺序列出,而是按字母排序的。可以用git show <tagname>查看标签信息:
$ git show v0.9
commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
Author: Michael Liao <askxuefeng@gmail.com>
Date: Thu Aug 22 11:22:08 2013 +0800

add merge
...

可以看到,v0.9确实打在add merge这次提交上。
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164

用命令git show <tagname>可以看到说明文字:
$ git show v0.1
tag v0.1
Tagger: Michael Liao <askxuefeng@gmail.com>
Date: Mon Aug 26 07:28:11 2013 +0800

version 0.1 released

commit 3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Tue Aug 20 15:11:49 2013 +0800

append GPL

还可以通过-s用私钥签名一个标签:
$ git tag -s v0.2 -m "signed version 0.2 released" fec145a

签名采用PGP签名,因此,必须首先安装gpg(GnuPG),如果没有找到gpg,或者没有gpg密钥对,就会报错:
gpg: signing failed: secret key not available
error: gpg failed to sign the data
error: unable to sign the tag

如果报错,请参考GnuPG帮助文档配置Key。
用命令git show <tagname>可以看到PGP签名信息:
$ git show v0.2
tag v0.2
Tagger: Michael Liao <askxuefeng@gmail.com>
Date: Mon Aug 26 07:28:33 2013 +0800

signed version 0.2 released
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (Darwin)

iQEcBAABAgAGBQJSGpMhAAoJEPUxHyDAhBpT4QQIAKeHfR3bo...
-----END PGP SIGNATURE-----

commit fec145accd63cdc9ed95a2f557ea0658a2a6537f
Author: Michael Liao <askxuefeng@gmail.com>
Date: Thu Aug 22 10:37:30 2013 +0800

branch test


如果标签打错了,也可以删除:
$ git tag -d v0.1
Deleted tag ‘v0.1‘ (was e078af9)

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使用命令git push origin <tagname>:
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
* [new tag] v1.0 -> v1.0

或者,一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 554 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
* [new tag] v0.2 -> v0.2
* [new tag] v0.9 -> v0.9

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
$ git tag -d v0.9
Deleted tag ‘v0.9‘ (was 6224937)

然后,从远程删除。删除命令也是push,但是格式如下:
$ git push origin :refs/tags/v0.9
To git@github.com:michaelliao/learngit.git
- [deleted] v0.9

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


配置别名
告诉Git,以后st就表示status:$ git config --global alias.st status

好了,现在敲git st看看效果。
当然还有别的命令可以简写,很多人都用co表示checkout,ci表示commit,br表示branch:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

以后提交就可以简写成:
$ git ci -m "bala bala bala..."

--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
在撤销修改一节中,我们知道,命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage操作,就可以配置一个unstage别名:
$ git config --global alias.unstage ‘reset HEAD‘

当你敲入命令:
$ git unstage test.py

实际上Git执行的是:
$ git reset HEAD test.py

配置一个git last,让其显示最后一次提交信息:
$ git config --global alias.last ‘log -1‘

这样,用git last就能显示最近一次的提交:
$ git last
commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2
Merge: bd6ae48 291bea8
Author: Michael Liao <askxuefeng@gmail.com>
Date: Thu Aug 22 22:49:22 2013 +0800

merge & fix hello.py

甚至还有人丧心病狂地把lg配置成了:
git config --global alias.lg "log --color --graph --pretty=format:‘%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset‘ --abbrev-commit"

来看看git lg的效果:

技术分享

 


为什么不早点告诉我?别激动,咱不是为了多记几个英文单词嘛!
配置文件
配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
配置文件放哪了?每个仓库的Git配置文件都放在.git/config文件中:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1

别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中:
$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com

配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。

 

 

我的git与github学习历程