手把手教你学会使用Git工具

178 阅读33分钟

什么是 Git?

  • 人工版本控制器是通过人工的复制行为来保存项目的不同阶段的内容,并添加适当的一些描述文字加以区分。
  • Git记录着不同版本之间变化的部分,通过程序完成上述人工版本控制行为

Git四种不同的记录状态

  • 未追踪(Untracked)表示当前的文件没有被管理和追踪
  • 已修改(modified)表示当前的文件的内容被修改了(对比之前)
  • 已暂存(staged)表示当前的文件已经被添加到暂存区了
  • 已提交(committed)表示当前的文件被提交了

Git文件的生命周期 Git文件的三种状态

Git的工作区域

Git提供了三个不同的工作区,用来存放不同的内容

  • 工作目录区(本地的工作目录区)
  • 暂存区域
  • Git仓库(和github远程仓库是不一样的)
  • 在工作目录区中可以修改或创建文件
  • 在暂存区域中可以暂存文件
  • 在Git仓库中可以找到暂存区的文件,提交更新

上手Git的基础配置操作1

  • 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改。
git config user.name "你的姓名"
git config user.email "你的邮箱"
  • 通过 --global 选项可以设置全局配置信息
git config --global user.name "你的姓名"
git config --global user.email "你的邮箱"
  • 检查配置选项,打印所有config
git config --list

上手Git的基础配置操作2

  • 创建仓库(repository),是 Git 保存数据记录的地方.
  • 进入希望纳入 git 版本控制的项目目录,使用 git init 初始化
git init

Git的工作流与基本操作

  • 当一个项目被 Git 初始化以后,只是表示我们希望通过 Git 来管理当前的这个项目文件的不同时期版本记录.
  • 但是这个时候项目中已存在的文件,或者以后新增的文件都是没有进入版本控制管理的,它们是 未追踪(Untracked) 的状态
  • 下图的效果是我在一个已经被Git初始化后的文件夹里新增了一个InfoTest.txt的文件,此时我通过git status来查看一下工作目录区中的文件状态,我们会发现此时该文件的状态就为Untracked,证明当前的文件没有被管理和追踪

查看工作区的文件状态

//查看工作区中的文件状态
git status


//一个实用的操作技巧是在敲命令到一半时如果忘记命令了可以按tab键会有提示
  • git status 显示乱码的问题可以在终端中输入:
git config --global core.quotepath false

Git如何将工作区文件添加到暂存区

  • stage可以理解为是一个‘staging area’的集结待命地区(舞台),我们通过add添加的文件,进入了准备区域等待被提交,这样的区域我们称之为‘暂存区’
  • 可以使用命令git add让工作目录区中的文件进入暂存区
//添加一个文件
git add 1.txt


//添加多个文件
git add 2.txt 3.txt


//添加整个目录
git add ./a



//添加多个目录
git add ./b ./c


//添加所有文件
git add .
  • 下图的效果是我们将我们工作目录区的文件都添加到了暂存区后的文件状态,现在该文件被改变为可提交至Git本地仓库

Git如何将暂存区文件提交到本地Git仓库

  • 可以使用git commit
  • 将暂存区里的改动给提交到本地 git 仓库,也就是为这次工作(一般会把某个具有特定意义的工作作为一个版本,它可以是多个文件的变化)
  • 每次提交同时会生成一个40位的哈希值,作为该次提交版本的唯一 id
  • 每次提交都需要填写备注信息
  • 执行git commit实际上git会到暂存区里去寻找目标文件,找到暂存区里的目标文件才会执行提交的更新

  • 第一种情况:直接敲入git commit会进入vim管理页面,需要先敲入i 才能进入插入的模式,此时才能输入描述信息,输入完描述信息后,需要按下键盘上的esc键才能退出插入状态,然后快速双击大写字母Z,才能退出vim管理页面成功提交本次信息。
  • 第二种情况:简写的提交命令git commit -m '提交时的描述信息'
git commit -m '提交时的描述信息'

  • 第三种情况:简写的提交命令git commit -a -m '提交时的描述信息'
//局限性在于它只适用于之前已经提交过暂存区的文件
//但是现在的状态是modified
//如果文件还是未追踪的状态(Untracked)是无法通过下面的指令直接提交的

git commit -a -m '提交时的描述信息

Git如何查看已经提交的历史记录

  • 第一种方法git log
  • 如果此时我们修改了已经提交过的文件,我们再来查看git status,此时的文件状态为modified,如果我们不顾这种状态,想要在这种状态下去直接提交该被修改的文件,我们会发现是提交不了的,原因是changes not staged for commit 我们需要重新将该文件添加至暂存区,在去提交文件。(可以参考上文中提到的Git生命周期图)

Git如何删除文件

  • 情况一:如果文件之前已经被提交过到暂存区,我们直接手动的删除工作目录区的文件(即手动右键通过菜单点击删除),查看一下状态 git status 我们会发现删除的文件被打印出 deleted f.txt,并且此时该文件依然在本地仓库库中(如果之前commit过的话)
  • 方法一:通过git rm <file>的命令删除, 我们创建了一个f.txt文件,并把它提交到了git仓库中,我们现在要通过命令行的方式删除这个f.txt文件,删除完成之后在重新提交,我们就可以告知git本地仓库我们不需要这个文件了
  • 方法一的缺点:我们虽然成功的删除git本地仓库中记录的该文件,但是该文件也在工作目录中被删除了,并不保留在工作目录区中,而是帮你把工作目录区中的指定文件也删除了,而往往我们的需求是仅删除本地git仓库中不需要的文件,而将工作目录区中的文件保留下来
//git认为是你自己手动删除的并没有通过git命令删除所以git可不认账
//这里我们要删除的文件是f.txt


git rm f.txt

  • 方法二git rm --cache <file>,这个操作是删除Git本地仓库中的指定文件,但是会保留工作目录区中的指定文件,执行完成之后指定文件在工作目录区中会得到保留,但是状态变为未追踪
//这里我们想要删除git本地仓库中的c.txt文件


git rm --cache c.txt

  • 错误操作示例情况:我们修改了一个已经被提交到了git本地仓库的文件(d.txt),此时我们想要直接通过git rm d.txt命令删除这个被修改的文件,我们会发现会有错误提示删除不了(安全机制),提交过的文件发生了修改如果没有提交就想删除会触发安全机制报错,因为文件如果没有经过提交就被删除找回时可能会丢失信息内容。所以你希望后期能找回就一定要先提交再去进行删除操作
  • 在错误操作示例情况中如果你真想删除可以执行强力删除的命令,git rm -f(force) <file> ,这个方法慎用

Git如何移动文件

  • 使用命令git mv file_from file_to(直接用这个命令简单)
  • 使用命令git mv file_from file_to等于使用mv file_from file_togit rm file_fromgit add file_to这三个命令。
  • 现在我们在本地工作目录区中新建一个名为first的文件夹和一个名为h.txt的文件,它们所处于同一层级的目录结构下,我们希望可以将h.txt文件移动到first文件夹里面,我们可以使用git mv h.txt first/h.txt,并且我们可以发现移动的过程中其实是对文件进行了重命名的操作。也就是说该流程是先去把工作目录区的指定文件删除然后添加一个与之前文件相同内容的一个重命名文件(相当于拷贝)进入工作目录区(并且已经移动到了我们指定的位置)
  • 模拟实现移动的流程:假设现在的工作目录区中有一个d.txt文件(它已经被添加进暂存区里了),我们在拷贝一个d.txt文件的副本并重命令dd.txt,然后通过指令git rm d.txt删除d.txt文件,在把重命名文件dd.txt添加进暂存区git add dd.txt,然后查看一下状态,我们发现git自己分析我们的操作是一个重命名的过程。
  • 这个操作能够成功完全是因为我们手动的拷贝了d.txt文件的副本,如果我们没有拷贝d.txt文件的副本,直接用touch dd.txt,然后再把d.txt文件删除git rm d.txt,再把添加dd.txt添加进暂存区,此时git会认为你只是想单纯的添加一个dd.txt文件,便去你的工作目录看有没有该文件,如果有则添加到暂存区成功,如果没有则失败。它是不会认为你是在进行重名名文件的操作的
  • 重命名情景模拟一:我们在移动文件时首先要告诉git后续的操作是重命名操作,即使用mv file_from file_to,然后再进行git rm file_fromgit add file_to的操作,这才会发生重命名的操作。

Git强大的查看命令:status

  • git status 打印文件状态(未追踪、已修改、已暂存)
  • git status -s 简化文件状态打印内容
  • short符号图解:
  • 个人记忆方式:靠右的M的功能几成呦喂(右未)
  • 如果我们删除了文件我们会发现 git status -s打印出 D cc.txt,大写D
  • 如果我们移动了文件我们会发现 git status -s打印出 R dd.txt ->dddd.txt,大写R

Git强大的查看命令:diff和log

  • 如果工作目录区的东西已经都被提交了,那么git diff会认为没有东西可以对比了,不返回任何东西
  • git diff查看当前文件的修改,主要看工作区目录文件和暂存区的区别
  • 情景实现一假设我现在的工作目录区中有tst1.txt的文件,它已经提交到了git本地仓库(说明其现在是有在暂存区的,因为本地git仓库是通过暂存区的内容来提交的),我们现在在本地工作目录区中直接改变tst1.txt里面的内容,在通过git diff命令来查看。重心在工作目录区
  • 情景实现一的解析:这里对比的是工作目录区和暂存区的区别,减减减(---)表示之前提交到暂存区里的内容(这里面的内容是旧的),加加加(+++)代表在工作目录区中的修改的还未再次提交到暂存区的(这里的内容是新的),@@ -1,3,+ 1,4 @@ 中的-1,3表示的是在之前提交到暂存区的内容的行数(旧的内容的行数)是一到三行,而+ 1,4表示的是在工作目录区中的修改的还未再次提交到暂存区的内容的行数(新的内容的行数)是一到四行,发生的是整个内容替换。

  • 情景实现二:我们之前通过 git diff对比的是工作目录区和暂存区的区别,如果我们想要对比的是暂存区和git本地仓库的区别又该怎么做到呢?这时候我们可以通过git diff --staged。这里会是之前提交的和在当前暂存区的文件的内容的对比,重心在暂存区
  • 情景实现二:我们在情景实现一的基础上把tst1.txt文件添加到暂存区,然后通过git diff --staged来比较现在的暂存区和git本地仓库中该tst1.txt文件的的区别

  • git log可以查看已经提交(commit)的日记记录,当日记记录太长想要退出时可以按q
  • 可以使用命令git log -p查看详细信息;或者使用命令git log -2 查看最近的n条信息;或者使用git log --stat 列出所有被修改的文件,以及简略的统计信息
  • 可以使用命令git log --pretty=oneline显示哈希和描述,或者使用命令git log --pretty=full 显示哈希作者和描述;

Git中的提交对象及master

  • 提交对象:Git 保存的并不是文件的变化或者差异,而是一系列的不同时刻的文件快照。快照记录的是以前的时间。在commit的时候会产生一个快照。
  • 提交操作时Git会保存一个提交对象,该对象中包含一个指向暂存内容快照的指针、作者姓名、邮箱、父对象指针以及提交输入信息。
  • 首次提交的对象没有父对象,其他普通的提交有一个父对象,多个分支合并的有多个父对象
  • Git 的分支本质上仅仅是指向提交对象的可变指针(master分支是指向提交对象的可变指针)。Git默认分支名master,它会在每一次的提交中自动前移
  • 一开始的master指向:
  • 在每一次的提交中自动前移,现在又提交了一次(C2)
  • 执行的效果为:

Git中创建分支

  • 查看分支(星号代表当前所处的分支):git branch
  • 创建分支:git branch branch1
  • 创建出来的新的分支,并不会改变我们当前所在的位置,即不会改变HEAD指针的指向
  • 切换到分支:git checkout branch1
  • 在不同分支上做出的对文件的修改的操作只会存在当前这个分支上
  • 切换分支,会将HEAD指向切换的分支
  • HEAD是一个特殊指针,该指针指向当前所在分支,是唯一的
  • master(分支)会在每一次的提交中自动前移,HEAD也会随着master自动前移,一起指向当前新的提交
  • 不管是master还是branch1只要是分支都会在每一次的提交中自动前移,此时HEAD也会随着master自动前移,一起指向当前新的提交
  • 查看分支指向+哈希:git log --oneline --decorate
  • 查看所有分支的提交并以树形图形式展开:git log --oneline --decorate --all --graph
  • 创建分支并将HEAD指向当前创建的分支的简写命令:git checkout -b 分支名
  • 通过HEAD来判断当前在哪个分支上面:(HEAD->master,branch1)说明当前的commit上有两个分支的指向,如下图
touch a.txt
git add a.txt
git commit -m '第一次提交'


touch b.txt
git add b.txt
git commit -m '第二次提交'


git checkout -b branch1
touch c.txt
git add c.txt
git commit -m '第三次提交'


git checkout master
touch d.txt
git add d.txt
git commit -m '第四次提交'

Git中merge的两种合并:正常合并和快速前移

  • 正常合并
touch  a.txt b.txt

git add a.txt

git commit -m '1'


git add b.txt

git commit -m '2'


//在这里创建了branch1分支并切换到了branch1分支上
git checkout -b  branch1


//查看当前创建的分支情况
git branch


touch c.txt d.txt

//在branch1分支下创建并提交了c.txt
git add c.txt

git commit -m '3'


//切回master分支上
git checkout master


//1和2是共有的提交
//3是branch1上提交的
//4是在master分支下提交的
git add .


git commit -m '4'


//会打印出当前在哪个分支下
git log --decorate --oneline


//回到branch1分支
git checkout branch1


//新文件
touch e.txt


//在branch1分支下添加并提交的e.txt
git add.

git commit -m '5'


//会打印出当前在哪个分支下
git log --decorate --oneline


//接下来要进行合并分支的操作
//这需要确定哪个是主分支 
//我们默认将master作为主分支



//切换为我们默许的主分支master
git checkout master



//把目标分支(branch1)向我当前的分支合并
//现在master分支下就有五个文件了
git merge  branch1


//默认只能打印出当前分支下的信息
git log


//--decorate是打印分支的信息
//--all打印所有分支的信息
//--graph在打印的前面形成一个树形的图
git log --decorate --oneline  --all --graph



//master分支自动向前移会带着HEAD一起移动到最新一次提交的地方

  • 执行效果为:
  • 快速前移:当master和branch1没有形成分叉,依旧是处于一条路径线,当HEAD落后于所要合并的分支,将会形成快速前移
//快速前移


touch a.txt b.txt c.txt


git add a.txt


git commit -m '1'


git add b.txt

git commit -m '2'

//创建了branch1并切换到了branch1
git checkout -b branch1


git add .


git commit -m '3'


git checkout master


//合并成功了出现了三个文件
git merge branch1


git log --all  --decorate  --oneline  --graph


//如果master和branch1在同一个commit提交上会发生快速前移
//Fast-Forward 快速前移


//master和branch1指向了同一个分支,当前的HEAD指向了master
  • 执行后如图:
  • 执行的效果为:
  • 快速前移是不太友好的,应该尽可能避免。因为此时通过git log不会显示出之前做过合并的操作,也就不知道之前其实有没有进行过merge操作(会有误解)
  • 使用--no-ff 禁止快速前移(可以commit此时记录描述为发生过合并操作)
git chekcout master

git merge --no--ff -m '输入合并操作的描述信息'  branch1  
//merge made by  the 'recursive' strategy


//此时记录描述为发生过合并操作
git log

Git中分支的操作:解决冲突,删除分支,取消分支合并

  • 分支冲突1: master 和 branch1 处于同一条commit路径上(直接级祖先关系),master 和 branch1 直接进行合并,不会引起冲突,分析 master 和 branch1中的修改是否一致,如果一致合并将会成为一次空合并(因为内容完全一致,没有合并的需要)
  • 分支冲突2: 如果不一致,是否修改的同一个文件内容,如果是同一个文件里面的内容则会发生合并冲突,如果是不同文件的内容则是没有关系的。
  • 情景重现一:


touch b.txt

git add .

git commit -m '这是新建的b文件'


//在master分支上创建了一个b.txt,然后修改一下文件其中的内容

git add .

git commit -m '修改了b文件的内容然后再一次提交'


git checkout -b branch2


//接下来我们修改一下b.txt里面的内容

git add .

git  commit -m '第二次修改b.txt里面的内容,但是这是在元素基础上修改再提交的'

//然后在切换为主分支
git checkout master


//此时在分支branch2上修改的b。txt的内容是不会显示到master中b.txt里面的
git   merge  branch2

//这是可以合并成功的!!!!
//但是会形成了一个Fast-forward
  • 情景重现二:
touch a.txt

git add.



git commit -m '新建了一个a文件'


//创建了一个branch1分支并切换到了branch1分支上
git chekcout -b branch1


//此时在branch1分支上修改了a.txt文件的内容
git add .


git commit -m '这是第一次在branch1分支上修改了a的内容'

git checkout master

//点开a.txt我们会发现我们在branch1分支上修改的内容是不会出现在master分支上的


//然后我们在master分支下也去修改a.txt的内容,随便新增一句话


git add .

git  commit -m '这是我在master分支下对a.txt文件做了修改的提交(总共改了两次了)'


//我们分别在两个分支上面对a.txt都做出来修改改动



//接下来我们要做的是把branch1分支上面的内容合并到master分支上面

//处在master上面

git merge  branch1
//CONFILICT(content)  merge confilct in a.txt


//合并失败  冲突
//手动筛选要保留的内容删除不需要的内容然后再一次重新提交

git add .

git commit -m '最终我筛选的结果内容'
  • 解决冲突:手动解决冲突部分,解决完成后再次提交,会以这次提交内容为准,合并完成后,分支就没有任何的后期用途了,这时候我们需要手动删除分支,以防止自己词穷的时候出现重复命名分支的情况。可以使用命令git branch -d 分支名称 或者git branch -D 分支名称
  • git branch -D 分支名称是在你还没有合并分支的时候你就想删除的情况下使用的,慎用
  • 当前HEAD所指向的分支,是无法删除,就好比如你无法在抓着自己头发的时候把自己抓离地面一样。你当前在此分支上,你是不能在此分支上删除此分支的。
  • 如果你刚刚执行git merge branch2合并分支的操作后,你反悔了想要取消合并,你可以紧接着在下一行命令中输入git merge --abort来取消合并。

touch d.txt


git add .

git commit -m '新建一个d文件'

git checkout -b branch4

//在这个 branch4分支上面修改d.txt文件

git add .

git commit -m '提交修改在branch4'


git checkout master


//在master上修改d.txt文件

git  add .

git commit -m '第二次修改d文件在master分支上'


//有两次不一样的修改操作了并且都提交了
//此时执行合并操作会有合并冲突
git merge branch4


//解决方式一:取消合并
git merge --abort

Git中撤销大集合

  • 撤销上一次提交信息:git commit '重新提交的信息' --amend
  • 撤销对文件的修改:git checkout -- <file>, 注意--的前后都需要有空格,这个撤销文件的修改必须是在该文件还没有添加到暂存区之前执行,会发现之前新增的内容被撤销了
  • 情景实现一:git checkout -- a.txt
git init 


touch a.txt


git add .

git status

//取消一个文件的管理的解决方法一:
//删除Git本地仓库中的指定文件
//但是会保留工作目录区中的指定文件
//但是文件状态变为未追踪
git rm --cached a.txt
git status  //untracked  a.txt


//因为文件状态变为未追踪所以需要重新添加进暂存区
git add .
git status  //new file : a.txt


//我们在这里修改了当前a.txt的内容

//modified : a.txt  (已经修改还未暂存)
git status  


//现在我们要撤销刚才对a.txt的修改

//方法一:手动删除已经添加的内容
git status


//方法二:
//执行下面的命令后会发现之前新增的内容被撤销了
//这里的checkout是用来撤销操作的要和切换分支的操作对比注意一下
//这个撤销文件的修改必须是在该文件还没有添加到暂存区之前执行
git checkout -- a.txt
  • 情景实现二:git reset HEAD a.txt,取消掉已经添加到暂存区里面的内容,变成了已经修改但是还没有提交到暂存区的状态
//再一次去修改a.txt的内容
//然后需要在将它添加进暂存区
git add .

git commit -m '修改后提交第一次内容'


touch b.txt
//在这里又对a.txt进行了修改新增了内容


//希望a.txt和b.txt两个文件分开作为两次commit来提交
//因为我们对a.txt和b.txt所做出的操作是不一样的
//所以我们希望通过两个不同的commit提交可以提交不同的描述信息


//但是如果我们误操作  
//直接git add .一次性把全部文件都放进暂存区的话
git add .


git status // modified a.txt  和 new file : b.txt


//方法一:
git rm --cached a.txt
git status  
//deleted a.txt 
//new file: b.txt
//Untracked files : a.txt
//如果此时提交会有deleted a.txt 这条多余的信息也被提交上去
//而我们本意是只想提交 new file b.txt这条信息


//方法二:
git add .


//取消暂存
//取消掉已经添加到暂存区里面的内容
//变成了已经修改但是还没有提交到暂存区的状态
git reset HEAD a.txt     
//Unstaged changes after reset


git status  //发现a.txt没有在暂存区里面了


git commit -m '只会包含已经在暂存区的内容'

  • 情景实现三:git commit -m '正确的信息' --amend
//如果提交的时候提交信息打错了那么可以撤回
//git commit -m ’打错了‘

git commit -m '正确的信息' --amend

//替换掉上一次commit提交的信息

  • 情景实现四:git commit --amend
//有两个已经修改的文件需要添加到暂存区然后提交
//一个是a.txt 一个是b.txt
//然后我们添加到暂存区并提交的文件只有a.txt
//我们是想两个文件都添加提交并且只有一条提交信息
git add a.txt
git commit -m 'one'

//方法一: 缺点提交信息出现两次
//git add b.txt 
//git commit -m 'two'

//想要合并一次提交的话

//方法二:进入vim模式   大写ZZ退出保存
git add b.txt
git commit --amend   

Git中reset和checkout本质

  • 可以用来撤销commit,但实质行为上并不是撤销操作,而是移动HEAD并且带上所指向的分支,重置HEAD及分支。即在HEAD之后的提交,因为当前不在任何分支上,就不会出现在工作目录中,起到撤销效果。该提交并未丢失,可以通过哈希找回。查看历史提交记录,可以通过命令 git reflog
  • 情景演示一:
git log  //查看提交的信息


git reset HEAD^  //撤销一条commit提交

//可以加上引号避免产生一些语句分歧
//撤销两条commit提交
//git  reset 'HEAD^^'  

git status

  • 情景演示二:撤销并不会把你之前commit的操作内容弄丢失
//该提交并未丢失可以通过哈希找回
git reset '哈希值'



//简单写法
git reset HEAD~50   //撤销50条commit



//找回方法二:
//只要通过commit提交的内容都是可以找回的
//撤销并不会把你之前commit的操作内容弄丢失
//撤销之后只是在当前的git log下不会存在
//查看历史commit提交记录
git reflogf


git reset '哈希值'

  • reset用来撤销commit的执行流程为:
  • checkout撤销对文件的修改的流程图:本质是签出指定commit,只会改变HEAD指向,并不会影响分支指向git chekcout -- <'文件名' > 会去找当前文件最近的一次提交,如果说当前最近的一次提交上面的话什么东西都没有,它会把当前工作目录的东西重置回在当前仓库里记录的内容
  • reset的更多操作之重置工作目录区,丢失暂存git reset --hard (尽量避免使用)
//在a.txt文件上进行修改

//添加进暂存区
git add .

git status  // modified a.txt Changes to be committed

//撤销一个commit提交
git reset 'HEAD^' --hard


git log


git status //nothing to commit,working tree clean
  • reset的更多操作之保留工作目录区,与原分支差异将放到暂存区git reset --soft
//在a.txt文件上进行修改

//添加进暂存区
git add .

//撤销一个commit提交
git reset 'HEAD^' --soft


//撤销一个commit提交后之前在暂存区里的a.txt文件还在
//不会造成之前在暂存区里的文件丢失的情况
git status   //modified a.txt changes to be committed
  • reset的更多操作之保留工作目录区,并且清空暂存区git reset --mixed(默认) ,这个只要切换到之前的commit上,原本在此commit上的暂存是还在的。

Git中存储及操作

  • 存储:当我们在一个分支中向暂存区添加内容,切换到另一个分支时,提交commit会带上另一分支中的暂存内容。
touch a.txt 

git add .

git status  //new file: a.txt

git commit -m '创建一个新的a文件'

//创建一个新分支并切换到分支branch1
git chekcout -b branch1

//此时我们再去修改a里面的内容
git status   
//modified a.txt changes not staged for commit


git add.


git status
//changes to be committed modified:a.txt


git checkout master


git checkout -b branch2

touch b.txt 


git status   
//当在一个分支中向暂存区添加内容,切换到另一个分支时
//该分支的暂存区中会有另一只分支暂存的内容
//因此提交commit会带上另一分支中的暂存内容。


//modified a.txt和Untracked files:b.txt
//现在branch2的暂存区里面有之前的 modefied 的a.txt还有一个untracked 的b.txt
//但是这个a.txt是在branch1的时候暂存的
//此时提交一定的话一定会把a.txt提交上去
  • 存储的使用:应该先把另外一个分支的暂存内容保存起来再来处理切换到另一分支时要在另一分支上提交的内容(和之前的分支的暂存区中的内容应该是没有关系的)
  • 切换到想要存储暂存区内容的分支执行:git stash 存储暂存区及工作目录修改文件 -在上面存储的基础上带上未追踪文件一同存储git stash -u
  • 打印所有存储内容git stash list
  • 将存储内容重新应用(默认不保留已暂存内容):git stash apply <stashName>,取出来的文件不在暂存区了需要自己在添加到暂存区
  • 将原暂存依旧以暂存进行取出:git stash apply --index ,取出来之后并把它放在了暂存区中
  • 移除存储:git stash drop,因为我们取出存储的时候是不会自动删除存储的,可是我都取出来了还不删除会造成性能浪费。
//接着上面的执行

//应该先把另外一个分支的暂存内容保存起来再来处理当前这个分支的要提交的内容


git checkout branch1


git status
//modified:a.txt  changes to be committed
//Untracked files:b.txt


//把当前暂存的记录保存起来
git stash  
//saving working directory and index state wip on branch1..



//查看存储的列表
git stash list  
//记住这个stash@{0}名字后期通过这个应用想要的存储
//stash@{0}:wip on branch1:76d44c1 '提交描述'


git status  
//现在只有显示b.txt未被追踪
//然而a.txt已经被存储起来了不会被打印出来
//Untracked files:b.txt


//在切换回branch2分支上
git checkout branch2


//将b.txt添加到此分支的暂存区
git add .



git status  
//现在只有b.txt文件
//new files:b.txt changes to be committed

//在branch2分支上提交
git  commit -m '这是b的创建'


git branch -d branch2   
//报错 我们在branch2分支下删除branch2分支是不行的


git checkout master  


//分支并未合并的删除方法
git branch -D branch2


//现在我们想要把之前暂存的内容取出来
//需要切换回之前执行存储操作的分支branch1
git checkout branch1


//查看我们存储过的内容
git stash list



//用这个命令取出来存储的内容
//此时取出来的文件不在暂存区了需要自己在添加到暂存区
//之前存储内容是在暂存区的我们存储之后在取出来却是不在暂存区了
//我们需要git add .把它在添加到暂存区,多了一步操作
git stash apply




//我们是从暂存区对它进行存储的
//所以最好的方式就是取出来之后它自己就在暂存区里
//而不是我们在多一步操作自己再去把它添加到暂存区
//这个命令取出来之后并把它放在了暂存区中
//执行完成之后可以通过git status来确认
git stash  apply --index



//git commit -m '提交'



//取出来之后他会还在存储中需要手动删除
git stash list
git stash drop
git stash list


//存储多个内容的时候   取出的格式要改变
//stash@{0} 通过git stash list来获取
git stash apply stash@{0} --index


//存储多个内容要删除的话  删除的格式也要改变
git stash drop stash@{0} --index


//默认存储的是在暂存区的内容以及工作目录中修改的这个文件
//不包含我们未追踪的文件

touch c.txt

git stash

git status

//可以通过下面的命令把未追踪的文件一样也存储起来
git stash -u 


git stash list 


git status


git stash apply stash@{0}  //取出到untracked


git status 

Git中rebase变基操作

  • rebase变基 :和merge同样都是进行合并操作的。 将当前一个分支的内容都移至另一个分支上。
  • rebase变基的工作流程 :首先找到两个分支的共同祖先, 然后对比当前分支与祖先的历次提交,进行提取相应修改,并保存为临时文件,将当前分支指向目标基底,最后将之前存为临时文件的修改依序应用
touch a.txt b.txt c.txt  d.txt e.txt

git add a.txt 

git commit -m '1'


git add b.txt 

git commit -m '2'


git log
//查看到有1和2两次提交


git checkout -b branch1

git add  c.txt 


git commit -m '3'


git add d.txt

//在当前的branch1分支上有1,2,3,4
git commit -m '4'

//切换回master
git chekcout master


git add e.txt

//现在的master分支上有1,2,5
git commit -m '5'


//125  1234
//查看log
git log --oneline --decorate  --graph -all


//merage是以master为主分支合并
//把branch1的内容向master合并
//即切换到master分支后执行 git merge branch1

//我们以master做为主分支,rebase一定是把你想要合并进去的这条分支(branch1)做为当前所在的分支(即要先切换到branch1上),即当前的HEAD要在branch1身上。
//把master作为基点(基础)然后把我branch1上面的内容进行合并
//先切换回branch1分支上
git checkout branch1



//把master做为基点---master上少了我们要的3和4
//执行完成之后会把branch1和HEAD也向上转移放到上面去
git rebase master
//Applying : '3'
//Applying : '4'
//这是我们要向上转移的内容


//当前处在同一条路径(线)上面
git log --oneline --decorate  --graph -all



//但是还没有合并所以要在转移到master分支上
git checkout master

//再去执行merge合并--会发生快速前移
git merge branch1



git log
  • rebase执行流程:

配置.gitignore文件

  • 配置忽略的文件.gitignore,列出忽略文本模式。有时候我们不希望git管理文件夹中的某个文件,但是每次git status都会显示出Untracked。我们就可以创建一个文件.gitignore
# 该行都会被忽略

* 匹配零个或多个任意字符

[abc]  匹配任意一个在方括号的字符


?  只匹配一个任意字符


** 表示匹配任意中间目录


! 忽略指定文件以外的文件或目录

[0-9] 在这个范围的都可以匹配

//忽略后缀为.doc,.gitignore的文件
*.doc
*.gitignore

tag标签

  • 我们经常看到下载的软件分为“xx版本”,这个“xx版本”其实就是我们说的标签,该标签指向一个commit对象,虽然我们也可以用这个commit对象进行版本的表述,但是由于哈希太长,并且没有规律,所以我们使用标签的方式,进行版本标注。
  • tag标签一旦打上它是不会移动的
  • 设置标签:git tag v1.0 默认在最新的commit提交上
  • 查看标签: git tag
  • 通过哈希值给指定commit添加标签:git tag v0.1 1094adb
  • 添加带有说明的标签:git tag -a v0.1 -m "描述信息" 1094adb
  • 删除标签:git tag -d v1.0
git  tag v1.0

//查看已经打上的tag标签
git tag


//tag它是不会移动的
git log--oneline  



//使用哈希值给指定commit添加标签:
git tag  v1.1 1094adb


//显示信息
git show  v1.1


//删除指定版本的标签
git tag -d v0.3

远程仓库命令

  • 创建远程仓库,仓库的名称默认origin,origin中有单独的master和HEAD指针,和本地仓库的HEAD或master并非一致。
  • 连接远程仓库:git remote add origin git@github.com:xxx.git
  • 提交master分支到远程仓库:git push -u origin master
  • 提交branch1分支到远程仓库:git push -u origin branch1
  • 克隆远程github项目到本地:git clone '克隆地址'
  • 拉取远程仓库项目到本地:git pull

  • 克隆远程仓库分支到本地分支上:git checkout -b branch1(分支名称) origin/branch1(想克隆的远程仓库的分支名称)
  • 拉取下来的分支默认是master,如果想要克隆别的分支一定要用这种方式

  • 只删除远程仓库分支:git push origin :branch1(只要删除的远程分支的名称)
  • 删除本地仓库分支:git branch -d branch1(要删除的本地分支名称)

  • 推送标签到远程仓库一个一个上传 git push origin v1.0
  • 推送标签到远程仓库全部一起上传上去标签名git push origin --tags
  • 删除远程仓库的标签git push origin :refs/tags/v1.0
//我们在本地仓库打的标签是不会自动到远程仓库的

//因为我们使用的是https协议所以每一次提交都需要输入账号密码
//可以配置一个ssh钥匙

git log --oneline


git push origin v1.0

git remote add origin  https://github.com/xx/xx.git

git push -u origin master

//登录一下账号
git branch

//上传branch1分支到远程仓库
//默认是不会把其他分支上传到远程仓库的
git push -u origin branch1


// cd../  返回上一层
git clone '项目地址'

git pull  拉取

ssh及编辑器命令行使用

  • 如果使用https协议那么每一次上传代码到远程github仓库都需要输入用户名和密码
  • 生成 SSH 秘钥,在github上头像下拉框中找到settings设置SSH, 将生成的文件填到对应的位置(生成的信息给到仓库的管理者)
ssh-keygen -t rsa -C "xxx@qq.com"
  • git 远程连接
git remote add origin git@github.com:xxx.git
  • 提交(同步)远程
git push -u origin master


# -u 简化后续操作
git push origin master
  • 克隆代码
git clone '远程仓库地址'
  • 远程分支
# 提交到远程(分支)
git push origin [本地分支名称]:[远程分支名称]



# 远程先创建好分支然后拉取到本地
git checkout -b [本地分支名称] origin/[远程分支名称]



# 拉取远程分支到本地
git pull origin [远程分支名称]:[本地分支名称]



# 查看远程仓库
git remote show origin



# 查看本地分支
git branch



# 查看远程分支
git branch -r



# 查看所有分支
git branch -a



# 删除本地分支
git branch -d [本地分支名称]



# 删除远程分支
git push origin --delete [远程分支名称]
# or
git push origin :[远程分支名称]


# 设置默认提交分支
git branch --set-upstream-to=origin/[远程分支名称] [本地分支名称]