最近看了廖雪峰老师的git教程,通俗易懂,操作性很强,是很好的入门教程,
网站链接:https://www.liaoxuefeng.com/,现记录下学习笔记
1、安装步骤
在Windows上安装Git
在Windows上使用Git,可以从Git官网直接(https://git-scm.com/downloads),然后按默认选项安装即可。安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
git-bash默认不能复制黏贴需要设置
使用的时候ctrl+c ,在git-bash中右键就可以复制
注意git-bash使用的命令与用cmd打开控制台命令有区别,切换e盘git-bash使用的命令是cd e: cmd打开控制台使用的命令是e:
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"$ git config --global user.email "email@example.com"
2、创建版本库
(1)在合适的地方新建一个文件夹learngit,cd 进入这个文件夹,pwd后会显示这个文件夹的目录
(2)通过命令$ git init把这个目录变成Git可以管理的仓库,这时learngit文件夹中多了一个.git目录,这个目录是Git来跟踪管理版本库的,不要改动,如果你没有看到.git
目录,那是因为这个目录默认是隐藏的,用ls -ah
命令就可以看见。
(3)用notepade++或者其它编辑器(不要用记事本) 新建一个文件readme.txt,并输入内容,放到learngit文件夹里
(4)用命令$ git add readme.txt告诉Git,把文件添加到仓库
(5)用命令$ git commit -m "wrote a readme file"告诉Git,把文件提交到仓库
为什么Git添加文件需要add
,commit
一共两步呢?因为commit
可以一次提交很多文件,所以你可以多次add
不同的文件,比如:
$ git add file1.txt$ git add file2.txt file3.txt$ git commit -m "add 3 files."
3、时光机穿梭
我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,修改后运行$ git status命令看看结果:
虽然Git告诉我们readme.txt被修改了,但如果能看看具体修改了什么内容,自然是很好的,通过命令查看修改 $ git diff readme.txt ,修改后跟上面是一样的通过$ git add readme.tx,$ git commit -m "wrote a readme file" 提交修改
提交后,我们再用git status
命令看看仓库的当前状态:
$ git status
(1) 版本回退
若提交了多个版本,我们需要回退到指定的版本,首先我们查看总共有多少个版本,通过命令 $ git log ,$ git log显示的信息比较全,比较眼花缭乱,可以使用 命令$ git log --pretty=oneline 显示简短信息
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,如果往上多的话写成HEAD~数字
。
$ git reset --hard HEAD^ //回到上一个版本
这时最新的那个版本通过命令 $ git log 查看已经不存在了,如果需要穿梭回来需要找到commit id
git reflog
用来记录你的每一次命令:$ git reflog
(2)工作区和暂存区
工作区(Working Directory)就是你在电脑里能看到的目录,比如我的learngit
文件夹就是一个工作区:
版本库(Repository)
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
每次修改,如果不add到暂存区,那就不会加入到commit中。
(3)撤销修改
1、未add到暂存区,只在工作区 $ git checkout -- readme.txt
2 、git add到暂存区了:庆幸的是,在commit之前,Git同样告诉我们,用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区: git reset HEAD readme.txt git checkout -- readme.txt 丢弃工作区的修改 3、现在,假设你不但改错了东西,还从暂存区提交到了版本库,怎么办呢?还记得版本回退一节吗?可以回退到上一个版本。删除并提交后可以通过 $ git reset --hard HEAD^回退到删除前(4)删除文件
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm
命令删了:
$ rm test.txt
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
:
$ git rm test.txt$ git commit -m "remove test.txt"
现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git checkout -- test.txt
4、远程仓库
自行注册GitHub账号。由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置,创建SSH Key ,cd 切换到learngit,通过命令
$ ssh-keygen -t rsa -C "youremail@example.com"
使用默认值不停的回车确认,会在C:\Users\Administrator文件夹里生成.ssh目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。然后打开GitHub网站,进入setting-SSH and GPG keys页面,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub
文件的内容,就有了自己的远程仓库。
(1)添加远程库
现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。
1、登录GitHub,在右上角的+里面有个New repository,在Repository name填入learngit
,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库:
2、在本地的learngit
仓库下运行命令:
$ git remote add origin git@github.com:tianyawhl123/learngit.git
添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。
3、就可以把本地库的所有内容推送到远程库上:
$ git push -u origin master
把本地库的内容推送到远程,用git push
命令,实际上是把当前分支master
推送到远程。
由于远程库是空的,我们第一次推送master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master
(2) 从远程库克隆
在创建远程库的时候勾选Initialize this repository with a README
,这样GitHub会自动为我们创建一个README.md
文件。创建完毕后,可以看到README.md
文件:
现在,远程库已经准备好了,下一步是用命令git clone
克隆一个本地库:
$ git clone git@github.com:michaelliao/gitskills.git
5、分支管理
(1) 创建与合并分支
首先,我们创建dev
分支,然后切换到dev
分支:
$ git checkout -b dev
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:
$ git branch dev$ git checkout dev
然后,用git branch
命令查看当前分支:
$ git branch
然后提交:
$ git add readme.txt $ git commit -m "branch test"
现在,dev
分支的工作完成,我们就可以切换回master
分支:
$ git checkout master
现在,我们把dev
分支的工作成果合并到master
分支上:
$ git merge dev
合并完成后,就可以放心地删除dev
分支了:
$ git branch -d dev
(2) 解决冲突
新建分支并指向此分支
$ git checkout -b feature1
修改readme.txt最后一行内容并在feature1分支上add和commit
切换到master
分支:
$ git checkout master
也修改readme.txt的最后一行,并在master分支上add和commit
现在master分支和feature1分支各自都分别有新的提交
此时在master分支上合并feature1会出现冲突
$ git merge feature1
Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,我们修改后后保存,再add和commit提交
用带参数的git log
也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
最后删除feature1分支
$ git branch -d feature1
(3) 分支管理策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
通常,合并分支时,如果可能,Git会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
合并dev
分支,请注意--no-ff
参数,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev
(4) Bug分支
软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,
合并分支,然后将临时分支删除。当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:
并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stash,现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:
$ git checkout master $ git checkout -b issue-101 现在修复bug,需要把“Git is free software ...”改为“Git is a free software ...”,然后提交:$ git add readme.txt
$ git commit -m "fix bug 101" 修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:$ git checkout master
$ git merge --no-ff -m "merged bug fix 101" issue-101 $ git branch -d issue-101 是时候接着回到dev分支干活了! $ git checkout dev工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:
$ git stash list
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了:
(5)多人协作
当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。
要查看远程库的信息,用git remote:
或者,用git remote -v显示更详细的信息:
$ git remote -v
origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push) 上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:$ git push origin master
如果要推送其他分支,比如dev,就改成:$ git push origin dev 但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
抓取分支
多人协作时,大家都会往master和dev分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:
$ git clone git@github.com:michaelliao/learngit.git
当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支。不信可以用git branch命令看看:$ git branch
* master 现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:$ git checkout -b dev origin/dev 现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:$ git add readme.txt $ git commit -m "add /usr/bin/env"
$ git push origin dev你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
$ git add hello.py
$ git commit -m "add coding: utf-8" $ git push origin dev 推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:$ git pull
git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin. 再pull:$ git pull
Auto-merging hello.py CONFLICT (content): Merge conflict in hello.py Automatic merge failed; fix conflicts and then commit the result. 这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:$ git add hello.py $ git commit -m "merge & fix hello.py"
$ git push origin dev因此,多人协作的工作模式通常是这样:
首先,可以试图用git push origin branch-name推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
(6)标签管理
在Git中打标签非常简单,首先,切换到需要打标签的分支上:
$ git branch
$ git checkout master
然后,敲命令git tag <name>就可以打一个新标签:$ git tag v1.0 可以用命令git tag查看所有标签:$ git tag 默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?方法是找到历史提交的commit id,然后打上就可以了:
$ git log --pretty=oneline --abbrev-commit
比方说要对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
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
小结命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
git tag -a <tagname> -m "blablabla..."可以指定标签信息;
git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;
命令git tag可以查看所有标签。
操作标签
如果标签打错了,也可以删除:$ git tag -d v0.1 因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。如果要推送某个标签到远程,使用命令git push origin <tagname>:$ git push origin v1.0
或者,一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:$ git tag -d v0.9
然后,从远程删除。删除命令也是push,但是格式如下:
$ 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>可以删除一个远程标签。