git笔记(廖雪峰git教程)及自己总结Q&A

1 篇文章 0 订阅

集中式和分布式的区别:svn和git

先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。

集中式的弊端:必须联网,而且在互联网的情况下,网速会很慢。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

 

 

下载版本,创建版本库:

安装成功后:

下载安装包链接:https://git-scm.com/download/win

安装目录是:E:\Program Files\PortableGit

安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!

做配置:

$ git config --global user.name "fang"

$ git config --global user.email "fang@1.com"

注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

git上:创建版本库:如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。

cd : change directory的简写,改变目录的意思,就是切换到哪个目录下, 如 cd e:\fff  切换 E 盘下面的fff 目录。

 

新建一个版本库的目录:

mkdir learngit

cd learngit

 

git init 进行初始化;

E:\git_df\learngit\.git目录不要随意改动目录下的文件,否则会把Git仓库给破坏了。

 

 

把文件添加到版本库:

使用Windows的童鞋要特别注意:

千万不要使用Windows自带的记事本编辑任何文本文件。

建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可。---设置---UTF-8

书写一个readme.txt,上传到仓库中:

简单解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。-m的信息最好不要省略。

git commit命令执行成功后会告诉你,1 file changed:1个文件被改动(我们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。

为什么Git添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:

总结:

现在总结一下今天学的两点内容:

初始化一个Git仓库,使用git init命令。

添加文件到Git仓库,分两步:

  1.  使用命令git add <file>,注意,可反复多次使用,添加多个文件;
  2. 使用命令git commit -m <message>,完成。

Git时光穿梭机:回退版本

总结;

要随时掌握工作区的状态,使用git status命令。 如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

 

版本回退:

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

commit id(版本号)而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,是唯一的,因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。

回退版本:

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

git reset --hard HEAD^  回退到倒数第一个版本

git reset --hard HEAD^^ 回退到倒数第二个版本

git reset --hard 1094a   ---回退到指定的版本:1094a(是commit id的前几个)

回退之后,还想知道曾经最新的版本,可以用命令:git reflog(记录每一步操作)

总结:

HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。

穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本

 

暂存区:Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念

 

工作区:就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区:

版本库(Repository):工作区一个隐藏目录.git,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。

你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

git add  file1-n :是把文件1-n都放在暂存区,git  commit  是一次性把暂存区的所有修改都提交到master分支中。

暂存区是Git非常重要的概念,弄明白了暂存区,就弄明白了Git的很多操作到底干了什么。

管理修改

为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。

第一次修改 -> git add -> 第二次修改 -> git add -> git commit

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

撤销修改

git checkout -- file可以丢弃工作区的修改:

git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区:

小结:

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

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

删除文件

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容

Git分支管理

但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。

创建和合并分支

head指针指向谁,就是这个分支。

head指向master,就是master分支,

指向dev,就是dev分支;

切换到git的目录E:\git_df\learngit\.git,再执行git命令:

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>

解决冲突:

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。

用git log --graph命令可以看到分支合并图。

git log --graph --pretty=oneline --abbrev-commit  查看分支合并细节

分支管理策略:

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

下面我们实战一下--no-ff方式的git merge:

首先,仍然创建并切换dev分支:

$ git checkout -b dev

Switched to a new branch 'dev'

修改readme.txt文件,并提交一个新的commit:

$ git add readme.txt

$ git commit -m "add merge"

[dev f52c633] add merge

 1 file changed, 1 insertion(+)

 

现在,我们切换回master:

$ git checkout master

Switched to branch 'master'

准备合并dev分支,请注意--no-ff参数,表示禁用Fast forward:

$ git merge --no-ff -m "merge with no-ff" dev

Merge made by the 'recursive' strategy.

 readme.txt | 1 +

 1 file changed, 1 insertion(+)

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

合并后,我们用git log看看分支历史:

$ git log --graph --pretty=oneline --abbrev-commit

*   e1e9c68 (HEAD -> master) merge with no-ff

|\ 

| * f52c633 (dev) add merge

|/ 

*   cf810e4 conflict fixed

...

 

可以看到,不使用Fast forward模式,merge后就像这样:

 

分支策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

所以,团队合作的分支看起来就像这样:

 

小结

Git分支十分强大,在团队开发中应该充分应用。

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

 

 

修改bug时:

幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

把工作区的内容保存:

git stash :把工作区的内容保存

git stash  list:查看工作区的内容

git stash pop:恢复的同时把stash内容也删了

git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

 

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

当手头工作没完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

 

开发一个新feature,最好新建一个分支;

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

 

但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?

master分支是主分支,因此要时刻与远程同步;

dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;

bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;

 feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!

 

小结:

查看远程库信息,使用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账号、无密码登录、克隆仓库

GitHub的神奇的网站,顾名思义,该网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。

在继续阅读后续内容前,请自行注册GitHub账号。由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

github的用户名和密码:

Sunnyfang3

https://github.com/Sunnyfang3/learngit.git

在继续阅读后续内容前,请自行注册GitHub账号。由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

ssh-keygen -t rsa -C "youremail@example.com"
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个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 Key”,你就应该看到已经添加的Key:

生成ssh秘钥:

C:\Users\zhanglei\.ssh

 

往github上添加本地的仓库,保证本地仓库和github上的库保持一致:

git remote add origin git@github.com:Sunnyfang3/learngit.git

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

git push -u origin master  ---第一次推时,就添加-u这个参数

 

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

以后再将本地的库内容

$ git push origin master  

遇到小问题:当连接暂时无法建立时,要选择yes,进行重试;(估计跟本地网络问题有关。)

 

 

 

总结:

 

要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;

关联后,使用命令git push -u origin master第一次推送master分支的所有内容;

此后,每次本地提交后,只要必要,就可以使用命令git push origin master推送最新修改;

分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!

 

如果克隆一个库:

要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。例如在本地:

git clone git@github.com:michaelliao/gitskills.git

Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。

 

 

标签管理:

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。

 

所以,tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

 

创建标签:

git tag <name>就可以打一个新标签:默认标签是打在最新提交的commit上的。

git tag查看所有标签:

 

git tag v0.9 f52c633  对某个commit id对象的版本打tag。方便对历史版本进行打tag‘

git show <tagname>查看标签信息:

git tag不是按照打tag的时间排序的,是按照字母排序的。

git tag -a v0.1 -m "version 0.1 released" 1094adb:还可以创建带说明的标签,用-a指定标签名,-m指定说明文字

注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。

 

 

 

git  tag  -d  tagname      删除一个标签:git tag -d v0.1;因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。

git push origin <tagname> :如果要推送某个标签到远程

git push origin --tags或者,一次性推送全部尚未推送到远程的本地标签:

 

如果标签已经推到远程了,要先删除本地的标签,然后再推送到远程即可;

git tag -d v0.9

git push origin :refs/tags/v0.9

要看看是否真的从远程库删除了标签,可以登陆GitHub查看。

小结:

命令git push origin <tagname>可以推送一个本地标签;

命令git push origin --tags可以推送全部未推送过的本地标签;

命令git tag -d <tagname>可以删除一个本地标签;

命令git push origin :refs/tags/<tagname>可以删除一个远程标签

 

小结:

在GitHub上,可以任意Fork开源仓库;

 

 自己拥有Fork后的仓库的读写权限;

 

 可以推送pull request给官方仓库来贡献代码。

 

 

https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128

列表生成式:

[x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

[x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

 [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']


>>> import os # 导入os模块,模块的概念后面讲到
>>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']

字典
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
...     print(k, '=', v)
...
y = B
x = A
z = C

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

生成器generator

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:d

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
调用g中的元素的方法是:next(g),
直到调取到最后一个元素,之后就报错StopIteration;
此外还有一次性展示生成器内的所有元素的方法,例如for循环:
>>> g=(x * x for x in range(10))
>>> for i in g:
...     print(i)
... 
0
1
4
9
16
25
36
49
64
81

另外一种生成生成器的方法:一个函数中如果含有yield说明该函数是一个生成器:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

 

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

举个简单的例子,定义一个generator,依次返回数字1,3,5:

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

迭代器

 

 

码云:

如果我们希望体验Git飞一般的速度,可以使用国内的Git托管服务——码云(gitee.com)。

 

和GitHub相比,码云也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示等功能。对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务,5人以下小团队免费。

 

码云的免费版本也提供私有库功能,只是有5人的成员上限。

 

自定义git:

配置别名:配置方法和shell命令中的差不多;

当然还别的命令可以简写,很多人都用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..."

 

配置文件:

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。

配置文件放哪了?每个仓库的Git配置文件都放在.git/config文件中:

给Git配置好别名,就可以输入命令时偷个懒。我们鼓励偷懒

 

 

管理git服务器,简单一看:

 

小结

 

 搭建Git服务器非常简单,通常10分钟即可完成;

要方便管理公钥,用Gitosis;    

要像SVN那样变态地控制权限,用Gitolite。

 

 

自己项目操作总结

删除文件的几种操作:

在git bash上操作,要切换到git仓库所在的目录:cd f:,然后切换到待删除文件的目录下:cd dir;

git rm test.txt
git commit -m "remove test.txt"

git push

网页上操作:登录仓库,按照路径,找到文件,点进去,然后点delete按钮--》确定,就可以删除文件。

注意:commit之后,是在本地仓库中已经提交了,但是远程仓库还是没有提交,所以要再push一下才能到远程仓库;
再push时,遇到下面的问题:


说明是要更新下代码;
然后进行git  pull先更新下本地代码,然后再git push把之前的修改都push上去;

 

git  bash使用

遇到问题:

1、删除文件时,有下面的报错:

If no other git process is currently running, this probably means a
git process crashed in this repository earlier. Make sure no other git
process is running and remove the file manually to continue.

 解决方法: 则把仓库目录里的.git/index.lock文件(文件是隐藏的)删除就可以了。删除index.lock不会影响Git使用。是说index文件被锁住了,但是还有一个index文件要进行操作。
一个仓库配有一个.git文件夹,在这个文件夹里面生成了一个index.lock文件,导致index文件不能被操作,所以把index.lock删除就ok

 

2、git bash使用一段时间之后,界面就不是从一行的开头开始展示 了;而且目录下内容展示不全面;需要重新打开一个网页:

暂时没有找到解决办法

 

3、git操作:

git上:上传一个文件的方法步骤:
add  ---commit---push


更改一个文件,然后提交:
pull下来-,然后打开,修改好后,push--》commit即可。

 

4、Git、Github、GitLab三者的区别:
Git - 版本控制工具 。
Github - 一个网站,提供给用户空间创建git仓储,保存用户的一些数据文档或者代码等。
GitLab - 基于Git的项目管理软件。
三者都是基于git的,可以说是git的衍生品。


 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值