git 详解

参考资料:廖雪峰的博客 https://www.liaoxuefeng.com/

 

在上文中,我们已经在linux系统通过源码成功编译安装了 git-2.7.0版本,现在我们继续学习如何使用 git 。

 

 

1、添加用户和邮箱

因为git是分布式版本控制系统,所以需要我们填写“用户名”和“邮箱”作为 本地分支库 在 git分布式版本库 中的唯一标识。

git config --global user.name  xxxx      # 设置本机的git用户名

git config --global user.email  xxxx        #设置本机的git邮箱

git config user.name        #查看用户名

git config user.email        #查看邮箱

git config --global user.name xxxx     #修改用户名

git config --global user.email    xxxx@xxx.com    #修改邮箱

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

 

2、创建版本库

mkdir git_repository        #选择一个合适的地方创建一个仓库目录

cd  git_repository

git  init       #仓库初始化,会在当前的仓库文件夹下生成一个隐藏的 .git文件,这样一个仓库就创建好了

 

3、添加文件到版本库

所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件、网页、程序代码等。不可识别图片、word文档等二进制文件的具体改动。

 

mkdir document    #在 git_repository 仓库创建存放文档的子目录,并向目录(工作区)中上传了 readme.txt 文本文件

git add document/readme.txt       #用 git add 命令告诉 git ,把文件从工作区添加到版本库(也叫暂存区,就是 .git 文件夹)

git commit -m "wrote a readme file"    #用 git commit 命令告诉 git ,把文件提暂存区交到本地版本库,-m 参数后面是本次版本提交的说明和备注,以便追溯

 

注:

1) git add <file> ,也可以添加多个文件,git commit 会将添加的文件一次性提交。

2) 对于已存在的文件,继续 git add <file> ,可以将该文件 commit 到版本库

3) git add 、git commit -a 会把本地修改内容全部提交。

操作流程小结:git init 初始化仓库,git add <file> 添加文件到暂存区,git commit 将暂存区stage 的内容提交到分支版本库。

4) git add -a    #将提交所有变化

    git add -u    #提交修改和删除文件,不包括新增文件

    git add .     #提交修改和新增文件,不包括删除文件

 

4、版本追溯、对比、还原

我们修改一下 readme.txt 文件中的内容,然后查看一下仓库状态。

git status     #让我们时刻掌握仓库当前的状态,提示 readme.txt 修改后还没有 commit,新文件 test.txt 需要 git add 添加到仓库。

注:On branch master     # 默认使用的是 master 主分支

git commit -a     #提交修改内容,弹出如下窗口,需要你把要提交的内容前面的 # 号注释去掉,然后保存并退出

显示提交已成功:

 

git diff <file>     #对比 工作区版本库 的不同之处,绿色内容相对版本库是新增内容,对比之后再 git commit -a 就放心多了

 

git checkout -- <file>    #直接检出最新版本的文件,覆盖当前文件。适用于文件被改乱了改错了,直接还原。

 

小结:

1) git status 可以查看工作区状态,提示你有哪些文件是新增或被修改过的。

2) git diff <file> 可以查看文件的改动内容

3) git checkout -- <file>    干掉该文件所有的修改,还原到最新版本,一定要加 “--”,否则就是切换分支的命令了

 

5、查询历史 及 版本回退

git log     #由近及远查看历史版本

git log  --pretty=oneline    #防止眼花缭乱,单行输出历史版本

注:黄色字体是版本id,不使用数字号作为版本号,是因为git是分布式版本管理,防止多人在同一版本库里工作的版本号冲突

 

git  reset --hard  HEAD^    #回退版本:HEAD^ 上个版本; HEAD^^ 上上个版本; HEAD~10 往上10个版本

回退前有4个版本,然后执行回退:

最近的一个版本已被回退,回退后的结果,且回退后根据 git diff 来看回退后不需要再 commit:

cat readme.txt    #看内容是否已被回退:刚才提交的第6点已经被回退了

 

问1:刚回退之后,我又想再还原到 id 为 f2dad... 的那个最新版本,该怎么办呢?

git  reset  --hard  <版本号id>     #指定 id 回退到某个版本

刚刚回退了的版本又被还原回来了~

 

问2:昨天回退了最新版本,今天后悔了,但是我已经不记得最新版本的 id 了,我该怎么还原回去呢?

git  reflog  readme.txt  #这个命令记录了你每一次执行的命令

从图中可以看出,git  reflog 记录了最后一次 commit 的版本 id,我们就找到了提交过的最新版的文档的 id,以此还原。

 

小结:

1) git log 查看提交历史,以便确定回退版本

2) git reflog 查看命令历史 和 版本号。以便知道对哪个版本做过什么

 

6、工作区与版本库的概念

工作区:存放文档、代码的地方(git_repository 文件夹)

版本库:工作区里面有个隐藏的 .git 文件夹,这个文件夹就是版本库/暂存区

工作原理:git commit <file> 命令只会提交已经 git add 过的内容,即 commit 提交的是版本库 stage 区的内容,而不会提交工作区的内容。做个实验理解一下。

1) 对 readme.txt 文件修改第一次,执行 git add

2) 对 readme.txt 文件修改第二次,不 git add

3) git status

可发现:绿色字体表示第一次提交的修改可以被commit,红色字体表示新修改没有被 add 到 stage 区,不能 commit

4) git commit -m "备注内容"     

# 测的时候一定要加 -m 参数,git commit、git commit -a 都把我没 add 的内容也给 commit 了

5) git diff readme.txt     #对比工作区版本和版本库版本

6) 9是修改后被 add 到 stage 区的,10 只做了修改没有被 git add,commit 只提交了9,显示 10 和版本库是不一样的

 

结论:git 优秀的地方在于跟踪和管理修改而非文件,这些修改需要 git add 后才会存放在 stage 区。

 

删除文件

方法1:从工作区删除文件,然后 git commit  <file>

方法2:git  rm  <file>    #从版本库到工作区全都删除

 

7、提交远程仓库(介绍先有本地库,后有远程库,该如何关联)

我们使用 GitHub 作为远程仓库,注册 GitHub 用户 && 登录,创建一个你的仓库

1) 在你的仓库,有默认的 master 主分支,可以从 master 继续创建副分支

2) 也可以把本地 git 仓库关联到 GitHub 的远程仓库下面

 

git remote add origin https://github.com/Jingjp/repository01.git    

# 给本地仓库关联一个远程仓库,地址 https://github.com/Jingjp/repository01.git,标签为 origin

git push -u origin master    

#把本地 master 分支内容推送到远程仓库 origin 分支下。第一次推送时,我们使用了 -u 参数,git 会把本地 master 分支和远程的 origin分支关联,以后推送或者拉取远程仓库内容就可以简化命令了。

git push origin master     #把本地 master 分支上提交了的内容推送到远程仓库 origin 下

git push origin  : master  #如果本地分支没写,就会提交一个空分支,相当于删除远程分支

 

 

小结:

git remote add origin https://github.com/Jingjp/repository01.git    #给远程主机添加标签

git push -u origin master    #提交当前分支到 origin 的 master 

git push origin master   

git branch --set-upstream-to origin/<branch-name> <branch-name> #将"本地"和"远程"关联

 

 

8、从远程仓库克隆

从零开发的情况下,最好是先创建远程库,然后从远程库克隆到本地

首先登录 GitHub,创建一个新的仓库 repository02,创建的时候勾选初始化一个 README.md 文件

 

远程库创建好了,我们在本地 linux 找好存放仓库的位置,就可以使用 git clone 命令克隆远程库了

git  clone  https://github.com/Jingjp/repository02.git

git  clone -b  dev  https://github.com/Jingjp/repository02.git    #从指定远程分支克隆

(git支持多种协议,如果不能使用https,就用 git  clone git@github.com:Jingjp/repository02.git)

非常完美,repository02 中有 .git 、README.md 两个文件

 

8.1 如果想指定标签如何克隆

 

9、远程代码推拉

 

向远程仓库推送 - push

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

$ git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。

如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。

$ git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

 

删除远程分支:

如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

$ git push origin :master
# 等同于
$ git push origin -d master (这个分支需先在本地checkout,才可以删除远程)

上面命令表示删除origin主机的master分支。

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。

$ git push origin

上面命令表示,将当前分支推送到origin主机的对应分支。

如果当前分支只有一个追踪分支,那么主机名都可以省略。

$ git push

如果当前分支与多个主机存在追踪关系,则可以使用 -u 选项指定一个默认主机,这样后面就可以不加任何参数使用git push。

$ git push -u origin master

上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。

不带任何参数的git push,默认只推送当前分支,这叫做simple方式。此外,还有一种matching方式,会推送所有有对应的远程分支的本地分支。Git 2.0版本之前,默认采用matching方法,现在改为默认采用simple方式。如果要修改这个设置,可以采用git config命令。

$ git config --global push.default matching
# 或者
$ git config --global push.default simple

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。

$ git push --all origin

上面命令表示,将所有本地分支都推送到origin主机。

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用 –force 选项。(连推送带合并代码)

 

$ git push --force origin

 

上面命令使用 –force 选项,结果导致在远程主机产生一个”非直进式”的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用–force选项。

最后,git push不会推送标签(tag),除非使用–tags选项。

$ git push origin --tags

 

有时候当远程xxx分支被删掉了后,用git branch -a 你还可以看到本地还有remote/origin/xxx这个分支,那么你可以使用git fetch -p 这个命令可以帮你同步最新的远程分支,并删掉本地被删了的远程分支

 

 

从远程仓库拉取 - pull

    取回远程主机某个分支的更新,与本地的指定分支合并

       git pull origin <远程分支>:<本地分支>

    1) 如果与当前分支合并,可省略本地分支名

        git pull origin <远程分支> 

        相当于:git fetch origin <远程分支>

                     git merge origin/<远程分支>

    2) 如果当前分支与远程分支存在追踪关系

        git pull origin

    3. 如果当前分支只有一个追踪关系

        git pull

    4) 手动建立追踪关系

        git branch --set-upstream master origin/next

    5. 清理远程已删除本地还存在的分支

        git fetch --prune origin

        或者 git fetch -p

        或者 git pull -p

 

 

git 切换到远程分支

如果没有clone,先clone

$ git clone ...

查看远程分支

$ git branch -a

切换到远程分支

$ git checkout origin/master

切换到 origin/Release分支,并在本地新建分支 myRelease

$ git checkout -b myRelease origin/Release
Branch myRelease set up to track remote branch Release from origin.
Switched to a new branch 'myRelease'

 

 

 

10、分支的创建与合并

多人开发的情况下,每个人的代码库就是一个分支,单独开发互不影响,但最终会在某个时刻把分支代码合并,盗个图给大家理解下:

 

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

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

 

分支的创建与合并

cd  git_repository     #(之前创建的本地版本库),对库的 master 主分支创建副分支 dev

git  branch  dev    # 在“当前分支”创建新分支”dev

git  checkout  dev    # 切换到分支 dev

git  branch     #查看所有分支,dev 分支前面有个 *,表示当前正在使用的分支是 dev

 

我们来做下测试,在 dev 分支做一些修改,然后提交,最后将分支合并到 master。

1) 首先确认现在是 dev 分支,修改 readme.txt,并添加提交。

2)  git  checkout  master     # 切换回 master 分支

    git  branch     # 确认当前分支

3) git  merge  dev    # 合并“指定分支(dev)”到“当前分支(master)”,发现内容已经合并到 master

4) git branch -d dev    # 删除 dev,只留 master

    git branch -D dev    # 强行删除分支(如未合并过的分支)

因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

 

小结:

 

查看分支:git branch

创建分支:git branch <name>

切换分支:git checkout <name>

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

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

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

 

11、解决分支冲突

开始测试:

1) git checkout -b feature     # 创建并切换到新分支 feature

修改 readme.txt 中的内容,并提交

2) git checkout master     #切换回 master

继续对 readme.txt 做修改,并提交

3) git merge feature    # master 分支合并 feature

我们发现合并失败,查看 readme.txt 中的内容

4) 删掉 <<< === >>>,修改冲突的内容。

重新用master 分支提交,再合并 feature 分支。

5) 删除分支

结论:

1) 把冲突内容改成了新的内容,仍能合并成功。git 默认当人工处理过以后,即便有冲突也以处理过的为准,不再在同一个地方报冲突了。

2) master 合并 feature 分支成功,冲突内容也变成了手动处理过的内容,但返回 feature 分支看 readme.txt,内容还是原来的内容,没有被 master 同步

 

 

小结

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

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

 

12、分支管理策略

 

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

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

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

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

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

13. 标签(tag)的管理

首先明确:

  1. 标签没有分支的概念。当你在master分支打个1.0的标签后,这个标签在dev分支也能看到。且在dev也不能再重复使用这个标签。
  2. 指定标签克隆的代码,适合用来打包构建,不适合用来开发
  3. 当标签从v1.0 升级到 v2.0,指定v1.0克隆的代码是没有分支的,如果切换到具体分支如master。则master分支会包含克隆前远程master分支的最新内容。

 

指定标签去拉代码,更多的是用来使用这一版本的内容来运行或者构建打包。应用场景主要包括使用github开源的内容。

$ git clone -b 1.4.1 http://code.aliyun.com/test/springcloud.git

打上1.0的标签

$ git tag 1.0

查看标签列表

$ git tag

查看标签下内容及备注

$ git show 1.0

默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?

方法是找到历史提交的commit id,然后打上就可以了:

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

$ git tag 1.1 afdecb0

还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:

$ git tag -a 1.4.1 -m "add swagger2" 1094adb

删除标签,多个标签可一起删除:

$ git tag -d 1.1 1.2 1.3

如果要推送某个标签到远程,使用命令 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

 

14、git stash 储藏、恢复

应用场景:1、代码写到一半,突然一个bug需要紧急修复,或者有另一个新的任务需要优先完成

                2、pull 拉取代码时,和本地内容冲突,就需要先把本地修改储藏起来再 pull。

 

git stash    # 把当前工作“储藏”起来。

git stash save "注释内容"    # 储藏工作,并添加注释

git stash list    # 查看储藏的工作列表

git stash apply stash@{0}    # 将 stash@{0} 的工作恢复,不删除储藏列表

git stash pop stash@{0}    # 将 stash@{0} 的工作恢复,删除储藏列表

git stash drop stash@{0}    # 将 stash@{0} 从储藏列表删除

git stash clear    # 清空储藏列表

git stash branch <branchname> stash@{0}    # 创建一个新分支,并恢复储藏内容

 

15、多人协作开发

 


16、搭建 git 服务器

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值