git工具

廖雪峰—git
菜鸟教程
撤销commit

git是什么?

git是一个管理文件的工具。
当你需要做一个大工程的时候,文件的管理无疑是非常庞大的工作,因为你需要不断的修改更新文件内容,同时可能还要保留旧版本保证可以复原,这样就需要备份多个版本的文件。
并且在大多数情况下一个工程需要在多数人来共同维护,那么这种情况下不同人之间修改内容的合并也是非常麻烦的,这时使用git就可以很轻松的解决这些问题。

git的作用

  1. 对文件进行跟踪管理,记录修改的时间、内容、修改人
  2. 多人共同修改,自动合并修改的内容
  3. 远程提交,抓取

git使用

本地版本库

安装git

在ubuntu下安装git只需要一个命令即可:

sudo apt-get install git

安装完成后输入git ,就会出现帮助信息。

设置自己的个人信息:

$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"

当然一台设备上可以有多个仓库,不同的仓库可以设置不同的个人信息。
当使用git config命令的–global参数后,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

一、创建版本库及初始化

什么是git版本库?
你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:

$ mkdir learngit
$ cd learngit
$ pwd
/Users/michael/learngit

第二步,通过git init命令把这个目录变成Git可以管理的仓库:

$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

创建了一个新的仓库,并且在当前目录下会新增一个.git目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

附:ls -a 查看以“.”开头的隐藏文件。

工作区、暂存区和版本库

我们先来理解下 Git 工作区、暂存区和版本库概念:

工作区:就是你之前为了git创建的这个目录。
暂存区:临时存放的区域。
版本库:最终提交到的管理文件的地方。

下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:
git工具_第1张图片

git的基本操作

Git 常用的是以下 6 个命令:git clone、git push、git add 、git commit、git checkout、git pull。
git工具_第2张图片

  • workspace:工作区
  • staging area:暂存区/缓存区
  • local repository:版本库或本地仓库
  • remote repository:远程仓库

向版本库提交文件

首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动 ,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。

而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。

修改file1并提交:
在这里插入图片描述
将文件添加到仓库只需要2步:

  1. 添加到暂存区
git add filename
  1. 上传到仓库
git commit -m "备注"

双引号内可以添加本次提交的说明之类的。

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

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

查看提交的各种信息

修改之前的文件,继续提交
在这里插入图片描述

git log

为了清楚的给出文件提交的信息,git log 可以查看提交日志
git工具_第3张图片
“version_1”是我在提交时的说明信息。黄色的一大串数字是版本id。

附:如果你嫌输出的信息繁多,加上参数 --pretty=oneline 查看简要信息。

gitk

gitk 更清楚的查看提交文件的信息,以及分支情况等等:
git工具_第4张图片

git status

git status: 查看当前仓库的状态,显示变更的文件。
git工具_第5张图片

比较修改

git diff 可以用于查看版本之间的差异。

查看工作区与版本库之间的差异(这里我感觉是比较工作区和暂存区的差异,因为当你添加到暂存区就无法比较了):

git diff

将文件提交到暂存区之后,可以比较暂存区与版本库之间的差异:

git diff HEAD <file>

撤销修改

当你发现工作区与暂存区不一样时,你可以丢弃工作区的改动:

git checkout <file>		#丢弃工作区的改动

当你提交到暂存区,但发现错误时,可以取消暂存:

git reset HEAD <file>	

版本回退

当你发现你提交了错误的文件,要撤回,那么就使用git reset 命令吧。

要退回上一个版本,首先要知道当前版本:gitk查看,head指向的就是当前版本。

方法一:
git reset HEAD^   #将上一个版本回退到暂存区
git checkout 	  #将暂存区的文件丢回到工作区,那么这样工作区的文件就是上一个版本的了

方法二:
git reset --hard HEAD^		#直接退回上一个版本

既然head^ 是上一个版本,那么上上一个版本就是head^^ ,当然往上100个版本写100个 ^比较容易数不过来,所以写成HEAD~100。
在这里插入图片描述
那么我们现在退回到版本1了,但是又向恢复到版本2了,该怎么办呢?

只需要找到那个版本的版本id,然后:

git reset --hard <version_id>	#版本id不用写全,只需写前几位也可

但如果,你已经撤回很多天了,找不到版本id了该怎么办?放心git记得你每一次的提交和退回:

git reflog		#git记录了你在这个仓库的所有提交和退回,只需输入git reflog 即可查看

在这里插入图片描述
前面的黄色字体就是我们要的版本id啦。

git的版本回退非常迅速,只要一个指令就可完成。
其实在git中又一个head指针永远指向当前版本,我们在做的就是让head指向上一个或下一个版本。
然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。

┌────┐
│HEAD│
└────┘

└──> ○ version_3

○ version_2

○ version_1

改为指向version_2:
┌────┐
│HEAD│
└────┘

│ ○ version_3
│ │
└──> ○ version_2

○ version_1

删除文件

当你将文件提交到版本库,误删工作区文件该怎么办?可以从版本库恢复。

git checkout <file>

当你真的想删除一个文件时:

rm <file>		#从工作区删除文件
git status      #查看改动
git rm <file>   #从暂存区删除
git commit -m "rm file"		#提交改动

远程仓库

git 支持远程仓库(就像云一样存在)。

找一台电脑充当服务器的角色,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。

github:提供Git仓库托管服务的,只要注册一个GitHub账号,就可以免费获得Git远程仓库。
创建属于自己的github仓库,并添加密钥。廖雪峰—git

向github远程仓库推送

将本地仓库与远程仓库关联:

用法:git remote add [<选项>] <名称> <地址>
git remote add origin [email protected]:zjh123456-art/my-first.git
这是我的远程仓库,git把远程仓库的名字默认为origin。

Git支持多种协议,包括https,但ssh协议速度最快。

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

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

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

git push -u origin master

在向github远程仓库推送master分支时,可能会出现以下错误:
在这里插入图片描述
解决方案:git push报错

可以看到已经提交到github远程仓库了。
git工具_第6张图片
从现在起,只要本地作了提交,就可以通过命令:

git push origin master

把本地master分支的最新修改推送至GitHub。

从远程仓库克隆到本地

想要将远程库克隆到本地,输入:

git clone [email protected]:zjh123456-art/second_git.git    #地址一定要正确

即可,在当前目录下会生成second_git文件夹。

git 克隆所有分支到本地,并自动切换到tag 的提交
命令:git clone --branch [tags标签] [git地址] 或者 git clone -b [tags标签] [git地址]

例如:git clone -b V1.0.0 https://github.com/xxx/xxx.git

single-branch 指定下载tag所在的单个分支 (可以减少一些下载内容,缩减大小)
git clone -b --single-branch <地址>

depth 指定下载tag所在单个分支,并指定深度 (depth=1时只下载tag一个提交)
git clone -b --depth 1

分支管理

git 支持多个分支,每个分支之间互不影响。如你想要不影响现在分支上的状况,又想要提交修改,那么你就可以创建一个新的分支。
你在新分支上不停的修改提交,等到时机成熟时,就可以将新分支合并到主分支上,这样就万事大吉。

一开始只有一条master分支,head指向master:
git工具_第7张图片
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

创建分支

当我们创建了一个新分支dev,并让head指向dev,就表示当前分支时dev:

创建分支两种方法
方法一:
git checkout -b dev 	#创建dev分支,-b 切换到dev分支

方法二:
git branch dev			#创建dev分支
git checkout dev		#切换到dev分支

查看当前分支:
git branch

git工具_第8张图片
从现在开始就是向dev分支提交了,而不是master。
git工具_第9张图片

合并分支

当我们想要将两个分支合并时:

git checkout master			#切回主分支
git merge dev				#将dev分支合并到当前分支

注意: 主分支不能向其它分支合并。
git工具_第10张图片
当合并完成后,你甚至可以删除dev分支:

git branch -d dev

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

git工具_第11张图片

附:switch 也可以创建或切换分支(不过我的Ubuntu不支持):

git switch -c dev	#创建并切换到dev分支

git switch dev      #切换到dev分支

小结:

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch

切换分支:git checkout 或者git switch

创建+切换分支:git checkout -b 或者git switch -c

合并某分支到当前分支:git merge

删除分支:git branch -d

合并冲突

当我们在两个分支上都提交了新版本时,分支合并会产生冲突:
git工具_第12张图片
在这里插入图片描述
git status 也会提示:
git工具_第13张图片
查看同时修改的文件内容:
git工具_第14张图片
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容。

此时,就需要手动去修改冲突,两种修改方式:

  1. 只保留其中一个分支的修改,将另一部分删去。(git 的标记也删)
  2. 两个修改都保留,删去git标记

然后在主分支提交修改:

git add file1
git commit -m "手动修改冲突"

提交完成后,就变成了这样:
git工具_第15张图片
git log或gitk可以查看分支结构。

git log --graph			#查看分支合并图
c@c-virtual-machine:~/git_test$ git log --graph --pretty=oneline --abbrev-commit
*   dc6082e 手动修改冲突
|\  
| * 62903b7 dev 修改file1
* | af8be27 master 修改 file1
|/  
* ede5a3b git branch test
* e430d00 rm_test
* 7199da0 test
* f19880f version_3
* cb814bc version_2
* ae6e6ce version_1

接着删除分支就好了:

git branch -d dev

观察gitk 的分支结构,可以发现删除分支并没有删除分支路径,只是删除了dev 指针。
git工具_第16张图片

禁用fast forward模式

使用–no-ff 参数可以禁用fast forward模式,因为这相当于一次提交,所以可以加注释:

git merge --no-ff -m "备注" dev

合并完成后,分支图:
git工具_第17张图片
(fast forward方式合并,合并后dev和master指向的是同一个提交。)
合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

分支策略

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

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

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

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

所以,团队合作的分支看起来就像这样:
git工具_第18张图片

存储工作现场

Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
当你将修改的版本提交到暂存区时,使用命令:

git stash 

可以隐藏暂存区的内容,此时git status查看暂存区时干净的:

c@c-virtual-machine:~/git_test$ git status
位于分支 dev
无文件要提交,干净的工作区

刚才的工作现场存到哪去了?用git stash list命令看看:

git stash list

想要恢复工作现场,又两个办法:

方法一:
git stash apply			#恢复工作现场
git stash drop			#删除stash内容

方法二:
git stash pop			#恢复的同时删除stash内容

你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

git stash apply stash@{0}

git stash save “save message” : 执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别。

git stash show :显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

git stash show -p : 显示第一个存储的改动,如果想显示其他存存储,命令:git stash show stash@{$num} -p ,比如第二个:git stash show stash@{1} -p

复制提交

当我们在一个分支上做了一个提交,二另一个分支也想要做同样的修改怎么办?
是不是只有合并分支,或手动修改,git提供了cherry-pick命令,帮助我们只复制一个提交,这样就不用合并分支啦。

git checkout dev
git cherry-pick 4c805e2			#后面跟的是提交的版本id

复制提交时,git会提示冲突,这时需要手动去修改冲突在提交。
git工具_第19张图片

强行删除分支

当你在一个新分支上做了新的提交后,并没有合并,你想直接删除该分支,这时git会提醒你,没有合并(删了在这个分支上的提交全部作废),不能删除:
在这里插入图片描述
这是用 -D 可以强制删除分支:

git branch -D dev1

远程推送和抓取

git remote     #查看远程分支

git remote -v  #查看远程分支详细信息

当你没有推送权限时,就无法看到地址信息。
在这里插入图片描述

推送分支

git push origin <分支名>	#推送指定分支到远程分支       

抓取分支

当你git clone时从远程仓库抓取主分支,如果远程库存在dev分支,你可以

git checkout -b dev 

创建远程的origin的本地dev分支,然后在这个分支上提交并推送。

远程冲突

当你和你的小伙伴同时向远程dev分支提交时,会产生冲突:
git工具_第20张图片
此时需要先用git pull把最新的提交从远程dev抓下来,然后,在本地合并,解决冲突,再推送:

git pull

git工具_第21张图片
git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支连接,根据提示,设置dev和origin/dev的链接:

$ git branch --set-upstream-to=<远程库名>/<远程分支名> dev
分支 dev 设置为跟踪来自 myfrist_origin 的远程分支 dev。

输入git pull成功,但是合并有冲突,需要手动解决。

$ git pull
自动合并 file1
冲突(内容):合并冲突于 file1
自动合并失败,修正冲突然后提交修正的结果。

git工具_第22张图片

多人协作模式

  1. 首先,可以试图用git push origin 推送自己的修改;
  2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  3. 如果合并有冲突,则解决冲突,并在本地提交;
  4. 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
  5. 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令
    git branch --set-upstream-to origin/。

Rebase

标签管理

当你需要完成一个大版本需要发布时,你可以给此次提交打标签(内核版本)。

创建标签

首先,切换到需要打标签的分支上,然后,敲命令git tag 就可以打一个新标签:

git tag v1.0

可以用命令git tag查看所有标签:

$ git tag
v1.0

默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?
方法是找到历史提交的commit id,然后打上就可以了:

git tag v0.9 <版本id>

再用命令git tag查看标签。

查看标签详细信息:

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

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

git tag -a v0.1 -m "version 0.1 released" 1094adb

操作标签

如果标签打错了,也可以删除:

git tag -d <tagname>

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使用命令git push origin :

git push origin <tagname>

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

git push origin --tags

要删除远程标签就麻烦一点,先从本地删除:

git tag -d v0.9		删除本地标签
git push origin :refs/tags/v0.9			删除远程标签

使用GitHub

廖雪峰——git
gitee

自定义Git

自定义git

你可能感兴趣的:(笔记,git,github,bash)