博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GIT原理和常用命令速成
阅读量:5164 次
发布时间:2019-06-13

本文共 6866 字,大约阅读时间需要 22 分钟。

【第二次更新,2018-11-09,10:44:59】

几个好习惯:

checkout(检出or签出)之前git status,因为checkout 后工作区和暂存区文件不变,有时候checkout只是想看一下另一个分支的内容,而不小心修改了该分支

git stash pop之前git add  因为pop不能撤回,一旦pop错了会很麻烦(你就不知道那些是pop出来的,那些是自己修改的)

两个概念:<commit> and <branch> (图片来自网络)

中间哈希值ID表示的是提交,注意HEAD指针指向的是某次提交

上面master表示分支

图上这种HEAD指针指向的提交没有对应分支的状态,称作分离的头指针(detached head),这种状态只是偶尔会用到

 

【第一次更新,2018-05-25,13:29:16】

1、有关bare和 non-bare库

普通库(non-bare)使用 git init创建,在本地可以直接进行修改提交等等

裸库(bare)使用git init --bare创建,不存在和普通库一样的各种工程文件,只有.git文件,一般目录的取名都是XXX.git,主要用于多人同步开发时候使用(例如远程的github)

ps.有时候我们想要在本地的几台电脑上(或者服务器,虚拟机等等)协同开发,可能会需要从普通库clone 到一个普通库,还需要在新的库中pull push等

需要注意的几点:

(1)clone bare库和non-bare库的操作一样

(2)同一台电脑上,或者使用samba服务器远程登录下,可以把origin直接设置为本地路径,例如D:/123/123;不然就要使用ssh协议或者https协议

(3)向non-bare的库push之前要在这个non-bare库配置一下,不然默认是refused的。

指令为git config --local receive.denyCurrentBranch updateInstead()

 

以下是原文


 

【原创,2018-03-16,15:33:49】

刚开始学习GIT的时候,以为只要掌握几个基本的操作指令就万事大吉了。但是随着GIT使用的深入,如果不了解些原理就会遇到各种各样让人一脸懵逼的问题,所以还是要对GIT原理有一些基本了解,这里默认已经掌握常用的基本指令了。(随便搜教程看下就行,例如clone pull push add commit log reset status branch checkout差不多吧,文末也会记录一些常用命令)

ps. 文中列举了许多英文单词,因为在外文手册和help中经常会看到这些单词,而不容易得知其对应中文意思,所以这里把常用的概念注释了出来。

 

一、GIT原理

原理先从git-gui版本的visuallize history图开始说起,先举例子上图(win下):

(ps. win版本直接安装git-gui就好,linux上安装gitk,并且shell中用gitk --all & 执行)

这是git中的树状图,表示了版本的演进发展过程,每个节点在英文手册或者help中称为point。下方的节点表示父节点,上面的节点表示子节点,子节点由父节点演化得到。

1、每一个圆点表示一个开发版本,每次commit或者pull、stash等就会出现新的子节点,后面的文字表示commit时写的注释信息

2、左侧方框表示分支branch名称(例如master, average等),连线的节点表示该分支当前的版本。

3、黄色表示HEAD指针指向的point(其实就是更新2中所说的commit),point的哈希值ID在git-gui中可以查到或者git log中查到。

4、每一个仓库包括三部分:工作区、版本库(暂存区index和分支树tree),如图所示(图片来自网络)

图片来自网络

工作区:对应于当前仓库(repository)目录(linux叫目录,win叫文件夹)下除了.git文件夹外其他所有文件(其实也不包括exclude文件中列举的文件)

版本库:对用于.git中的文件,包括暂存区(stage/index)的数据 + 各个版本分支(按照上面3的说法就是指各个节点)的数据

5、文件分为三种状态:unstaged, stage,  commit之后的文件

git add 命令就是把unstaged的数据提交到缓存区表位staged状态

git commit 命令就是把staged的数据提交,生成一个新的point

git status 命令可以查看处于unstaged, staged 状态的文件,

其中unstaged文件又分为modified(之前存在的文件做出修改), untracked(新建文件)

ps. git status 输出结果中还给出了从stage撤回到unstaged, 从modified恢复修改之前的指令,untracked文件的恢复就是rm删除就可以了

 


 

 二、常用指令(尽量按照使用GIT时可能碰到的先后顺序写)

0、github初始配置(暴露码农本性了)

(1)生成秘钥对ssh-keygen -t rsa -C "your_email@youremail.com"

(2)github添加公钥

(3)验证是否成功ssh -T git@github.com

(4)设置每次commit的信息

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

$ git config --global user.email "your_email@youremail.com"

(5)设置orgin(如果需要的话,参见下文1)

初始设置 $ git remote add <origin> git@github.com:yourName/yourRepo.git

修改 git remote set-url <origin> git@github.com:yourName/yourRepo.git

列出所有远程库的源 git remote -v

 

1、GIT从零开始

(1)从远程主机下载已有的仓库开始

注意,git clone下来之后默认只会在本地建立一个分支(不管远程库有几个分支,本地建立的分支对应于remotes/origin/HEAD指向的分支),尽管如此,其他分支的信息也是会下载下来并通过隐藏的方式保存,如果想查看所有分支,需要使用git branch -a。如果需要本地建立其他的分支,需要手动创建。

a)ssh方式(关于SSH公钥秘钥的产生和设置这里就不提了,网上随便一搜就有

git clone git@域名:用户ID/仓库名称.git

b) https方式

git clone https://域名/用户ID/仓库名称.git

输入用户名和密码

(2)从本地主机新建仓库开始

git init

(3)本地仓库和远程仓库冲突合并

本地先设置origin(见上文0),然后fetch或者pull(见下文6)

 

2、本地分支的操作

git branch 查看本地分支

git branch -a 查看本地分支和远程分支

git checkout -b AAA BBB 在BBB节点(commit的ID或者branch名字都可以,所有branch的名字使用git branch -a查看)上建立名字为AAA的分支并切换到该分支

(缺省BBB:默认使用HEAD指针的节点)

git checkout -t BBB 建立与BBB分支同名的本地分支(此时的BBB分支只能是远程分支全名,例如remotes/origin/master)

git branch -d AAA 删除名字为AAA的分支(删除没有被合并过的分支要用-D参数)

(ps. 有一些节点没有分支名字并且不是现有分支的父节点,在GIT中会保存一段时间,之后就可能被删除了)

git checkout AAA 移动到已存在的分支AAA(移动HEAD指针)

ps1. 如果unstaged和staged的文件与将要移动的分支不冲突的话会直接带入到新的工作区,所以注意git checkout之前最好要commit,不然很可能工程会搞乱(不知道为啥git这么设计)

ps2. 移动HEAD指针参考2.5

 

2.5 checkout命令(检出or签出)

(1)检出分支或提交(移动HEAD指针)

git checkout <branch/commit> (注意2中的ps1)

(2)检出文件

git checkout <branch>/<commit> -- filename

把某个节点下的某个文件checkout到当前暂存区(即之前工作区该文件的所有修改被取代)

git checkout -- filename

缺省则表示HEAD指向的当前节点,应为是当前的commit节点也就不用加入暂存区了,这条命令常用于撤销工作区该文件的修改

(3)新建分支

参考上面的2

 

3、完成本次开发准备本地提交

(git status 查看文件状态)

git add 文件名/.(点表示所有unstaged文件)

git commit -m "xxx

 

4、版本回滚

分为两种情况:

a)HEAD指向有名字的分支,可以理解为把该分支(例如master分支)移动到HEAD指向节点的前辈节点,并且移动HEAD指针到该节点

b)HEAD指向没有名字的分支(哈希值表示),reset等价于移动HEAD指针的checkout指令

这里主要针对a情况

git log (-n 查看记录数)(显示当前节点的所有父节点)

git log XXX 查看XXX文件的commit记录

git reset --soft XXX 把当前分支移动到历史提交XXX上,工作区文件不变,版本库中有差异的文件直接放入到暂存区(index),即staged状态

git reset --mixed XXX (--mixed可缺省) 当前分支移动到历史提交XXX上,工作区文件不变,版本库中有差异的文件放入到unstaged状态

git reset --hard XXX 当前分支移动到历史提交XXX上,工作区文件也都全部还原到历史版本

ps1. reset不会立刻把git树中的节点删除掉,而是会保存一段时间

ps2. HEAD指针变形(HEAD^表示上一个父节点,HEAD^^上两个父节点)

ps3. git reset HEAD <filename>  表示撤销暂存区的某个add,工作区不变

 

5、push(同4)

(origin表示该仓库对应的远程仓库,在clone之后已经默认设置好了,不过可以修改也可以建立新的源)

git push origin AAA:BBB 把AAA分支推到远程BBB分支(缺省 “:BBB”:远程分支和本地分支同名,远程没有同名分支则新建;缺省“AAA”:删除远程BBB分支)

(缺省“AAA:BBB”:push HEAD指针指向的分支,远程分支和本地分支同名)

(缺省 "origin AAA:BBB"): 若源是惟一的,则origin可以省略,指令作用同上

 

6、pull(同4)

(1)pull = fetch + merge

(2)pull一般用于本地已经存在的分支,用于同步

git pull origin AAA:BBB(AAA是远程分支,BBB是本地分支)

(缺省:BBB表示本地分支和远程分支同名,缺省AAA:BBB表示HEAD分支,origin唯一的时候也可以缺省)

(3)fetch一般用于获得本地不存在的分支,或者已知本地和远程分支有冲突想要先检查区别再合并的情况

fetch会修改FETCH_HEAD指针,记录在本地的一个文件中,指向着目前已经从远程仓库取下来的分支的末端版本。(也当做一个分支名称就可以了)

git fetch origin AAA:BBB(同上)

这里比较坑的一点即是缺省AAA:BBB表示的是master分支,不!是!HEAD!

(4)git diff AAA:BBB 比较AAA分支到BBB分支的变化,如果结果太长建议使用重定向,让结果输出到文件(例如git diff AAA:BBB > a.diff )

(缺省:BBB,表示AAA分支到当前HEAD分支的变化,例如git diff FETCH_HEAD)

git  diff  可以查看当前没有add 的内容修改(不在缓冲区的文件变化)

git diff --cached查看已经add但没有commit 的改动(在缓冲区的文件变化)

git diff HEAD 是上面两条命令的合并

关于diff输出的标记符号:

参考:http://blog.csdn.net/zcube/article/details/42246331

@@ -AAA分支的起始行号,AAA分支的结束行号(如果之后一行逗号后面省略) +BBB分支的起始行号,BBB分支的结束行号(只有一行逗号后面省略) @@

(5)git merge AAA 表示AAA分支合并到当前分支(缺省AAA表示FETCH_HEAD分支合并到当前分支)

如果发生冲突,需要自己去文件中修改,文件中的标记如下:

<<<<<<<到=======是当前分支的文件内容,=======到>>>>>>>是合并文件的文件内容

 

7、栈

一般用于两种情况

(1)自己在本地上做了一些修改但由于没完成还不想提交,发现远程也做了一些修改,所以可以先把本地的修改加入到栈中,然后pull,在读出修改信息

(2)在开发中突然发现一个更重要的问题需要修改测试,可以把当前的部分没完成的工作加入到栈中

ps. 注意:暂存区的修改放入栈中并pop之后还是会进入到工作区

git stash show 当前栈中的所有条目

git stash show -p 栈中的所有修改(类似于git diff)

git stash -u把所有unstaged和staged的文件修改加入到栈中(没有-u新文件不加入栈中)

git stash pop 读出栈的修改(如发生冲突需要自己去修改)

git stash drop 扔掉栈中的第一条

git stash clear 清空栈

就先写到这里,其他的补充以后再添加

 

8、关于删除

(1)直接删文件

删除文件这一操作也是需要提交的,git会记录删除之前的所有文件修改信息

(2)git rm <filename>

 既删除文件,同时又删除git所记录过的该文件的所有版本信息

(3)git rm --cache <filename>

不删除文件,只删除git记录的版本信息,常用户某些文件的修改记录到了版本库中,但后来发现可能并不需要记录这些文件的版本信息(不然只要一变动就得commit很麻烦而且使分支树很混乱),这是可以加入到gitignore文件中,并用这种方法删除版本库中的记录

 

9、跨平台开发的换行符问题

WIN ---- '\n\r' ---- 0D0A ---- CRLF

UNIX/LINUX/OS X ---- '\r' ---- 0A ---- LF

MAC OS ---- '\n' ---- 0D ----CR(现在没人用这个了吧)

ps1. CR: carriage return; LF: linefeed

ps2. 现在有一些编辑器不管是以哪种换行符结尾都是可以识别的(也就是说显示是正确的),所以说虽然有可能在windows上看到的格式正确,也不一定说明文件就是按照CRLF作为换行符的(windows记事本只识别CRLF)

# 提交时转换为LF,检出时转换为CRLF

git config --global core.autocrlf true
# 提交时转换为LF,检出时不转换
git config --global core.autocrlf input
# 提交检出均不转换
git config --global core.autocrlf false

GIT默认是第一种,同时也可以设置下

# 拒绝提交包含混合换行符的文件

git config --global core.safecrlf true
# 允许提交包含混合换行符的文件
git config --global core.safecrlf false
# 提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

 

10. git help XXX 某个指令的帮助文档

tab自动补全

转载于:https://www.cnblogs.com/qh4869/p/8577320.html

你可能感兴趣的文章
Caroline--chochukmo
查看>>
iOS之文本属性Attributes的使用
查看>>
从.Net版本演变看String和StringBuilder性能之争
查看>>
Excel操作 Microsoft.Office.Interop.Excel.dll的使用
查看>>
解决Ubuntu下博通网卡驱动问题
查看>>
【bzoj2788】Festival
查看>>
执行gem install dryrun错误
查看>>
HTML5简单入门系列(四)
查看>>
实现字符串反转
查看>>
转载:《TypeScript 中文入门教程》 5、命名空间和模块
查看>>
苹果开发中常用英语单词
查看>>
[USACO 1.4.3]等差数列
查看>>
Shader Overview
查看>>
Reveal 配置与使用
查看>>
Java中反射的学习与理解(一)
查看>>
C语言初学 俩数相除问题
查看>>
B/S和C/S架构的区别
查看>>
[Java] Java record
查看>>
jQuery - 控制元素显示、隐藏、切换、滑动的方法
查看>>
postgresql学习文档
查看>>