zoukankan      html  css  js  c++  java
  • Git命令教程

    你的本地仓库有 Git 维护的三棵“树”组成,这是 Git 的核心框架。这三棵树分别是:工作区域、暂存区域和 Git 仓库

    工作区域(Working Directory)就是你平时存放项目代码的地方。

    暂存区域(Stage)用于临时存放你的改动,事实上它只是一个文件,保存即将提交的文件列表信息。

    Git 仓库(Repository)就是安全存放数据的位置,这里边有你提交的所有版本的数据。其中,HEAD 指向最新放入仓库的版本(这第三棵树,确切的说,应该是 Git 仓库中 HEAD 指向的版本)。

    Git 的工作流程一般是:

    1. 在工作目录中添加、修改文件;

    2. 将需要进行版本管理的文件放入暂存区域;

    3. 将暂存区域的文件提交到 Git 仓库。

    因此,Git 管理的文件有三种状态:已修改(modified)、已暂存(staged)和已提交(committed),依次对应上边的每一个流程。

    一初始化Git

    在自己方便的盘中新建一个文件夹,这里以MyProject为例,注意路径中不要含有中文字符。打开cmd命令窗口,操作如下:

    C:Userslenovo>F:
    F:>
    F:>cd MyProject
    F:MyProject>
    #初始化Git项目,成功后创建有一个.git隐藏文件
    F:MyProject>git init
    Initialized empty Git repository in F:/MyProject/.git/
    #在文件夹MyProject中添加一个文本文件README,md格式指Markdown格式(建议使用Notepad++编辑)
    #然后输入以下命令将文件加入暂存区
    F:MyProject>git add README.md
    #将文件提交到git仓库(-m表示添加本次提交的说明,强制要求写的)
    F:MyProject>git commit -m "add a readme file"
    [master (root-commit) 9e08cf4] add a readme file
     1 file changed, 1 insertion(+)
     create mode 100644 README.md

    二.D:>Clone>git clone 目标  克隆github 上别人的代码

    三.使用git status查看当前状态

    F:MyProject>git status
    On branch master
    nothing to commit, working tree clean //表示没有提交过代码,很干净
    
    F:MyProject>git status
    On branch master
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            LICENSE(红色)
    
    nothing added to commit but untracked files present (use "git add" to track)

    Untracked files 说明存在未跟踪的文件(下边红色的那个)

    所谓的“未跟踪”文件,是指那些新添加的并且未被加入到暂存区域或提交的文件。它们处于一个逍遥法外的状态,但你一旦将它们加入暂存区域或提交到 Git 仓库,它们就开始受到 Git 的“跟踪”。

    这里圆括号中的英文是 git 给我们的建议:使用 git add <file> 命令将待提交的文件添加到暂存区域。

    F:MyProject>git add LICENSE
    
    F:MyProject>git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            new file:   LICENSE(绿色)
    
    use "git reset HEAD <file>..." to unstage 的意思是“如果你反悔了,你可以使用 git reset HEAD 命令恢复暂存区域”。如果后面接文件名,表示恢复该文件;如果不接文件名,则表示上一次添加的文件。
    F:MyProject>git reset HEAD
    
    F:MyProject>git status
    On branch master
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            LICENSE(红色)
    
    nothing added to commit but untracked files present (use "git add" to track)
    

    再次添加到暂存区域,然后执行 git commit -m "add a license file" 命令:

    F:MyProject>git add LICENSE
    
    F:MyProject>git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            new file:   LICENSE
    
    
    F:MyProject>git commit -m "add a license file"
    [master 9fdf9f4] add a license file
     1 file changed, 7 insertions(+)
     create mode 100644 LICENSE
    
    F:MyProject>git status
    On branch master
    nothing to commit, working tree clean
    

    关于修改

    突然发现版权那块忘了写上自己的名字了……
    打开 LICENSE 文件,将 Copyright (C) <year> <copyright holders> 改为 Copyright (C) 2016 FishC,保存……

    执行 git status 命令:

    F:MyProject>git status
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
            modified:   LICENSE(红色)
    
    no changes added to commit (use "git add" and/or "git commit -a")
    

    由于你对工作目录的文件进行了修改,导致这个文件和暂存区域的对应文件不匹配了,所以 Git 又给你提出两条建议:

    • 使用 git add 命令将工作目录的新版本覆盖暂存区域的旧版本,然后准备提交
    • 使用 git checkout 命令将暂存区域的旧版本覆盖工作目录的新版本(危险操作:相当于丢弃工作目录的修改)

    还有一种情况我们没分析,大家先把新版本的文件覆盖掉暂存区域的旧版本:

    F:MyProject>git add LICENSE
    
    F:MyProject>git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   LICENSE(绿色)
    

     然后我们打开 LICENSE 文件,将 FishC 改为 FishC.com,保存……

    F:MyProject>git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   LICENSE(绿色)
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
            modified:   LICENSE(红色)
    

     这次情况是:被绿的 LICENSE 说明文件存放在暂存区域(待提交),同时红色的 LICENSE 说明文件还在工作目录等待添加到暂存区域。

    这种情况你应该意识到这里存在两个不同版本的 LICENSE 文件,这时如果你直接执行 commit 命令,那么提交的是暂存区域的版本(FishC),如果你希望提交工作目录的新版本(FishC.com),那么你需要先执行 add 命令覆盖暂存区域,然后再提交……

    一步到位

    从工作目录一步添加到仓库:git commit -am “说明”

    F:MyProject>git commit -am "change the license file"

    -a的意思是add。

    git log 查看历史操作记录

    Git使用教程5---回到过去

    有关回退的命令有两个:reset 和 checkout

    回滚快照

    注:快照即提交的版本,每个版本我们称之为一个快照。

    现在我们利用 reset 命令回滚快照,并看看 Git 仓库和三棵树分别发生了什么。

    执行 git reset HEAD~ 命令:

    注:HEAD 表示最新提交的快照,而 HEAD~ 表示 HEAD 的上一个快照,HEAD~~表示上上个快照,如果表示上10个快照,则可以用HEAD ~10

    此时我们的快找回滚到了第二棵数(暂存区域)

    git reset HEAD~ 命令其实是 git reset --mixed HEAD~ 的缩写, --mixed 选项是默认的。

    默认
    git reset HEAD~ 命令其实影响了两棵树:首先是移动 HEAD 的指向,将其指向上一个快照(HEAD~);然后再将该位置的快照回滚到暂存区域。
    --soft选项
    git reset --soft HEAD~ 命令就相当于只移动 HEAD 的指向,但并不会将快照回滚到暂存区域。相当于撤消了上一次的提交(commit)。一不小心提交了,后悔了,那么你就执行 git reset --soft HEAD~ 命令即可(此时执行 git log 命令,也不会再看到已经撤消了的那个提交)。
    --hard选项
    reset 不仅移动 HEAD 的指向,将快照回滚动到暂存区域,它还将暂存区域的文件还原到工作目录。
    

    回滚指定快照
    reset 不仅可以回滚指定快照,还可以回滚个别文件。

    命令格式为: git reset 快照 文件名/路径

    这样,它就会将忽略移动 HEAD 的指向这一步(因为你只是回滚快照的部分内容,并不是整个快照,所以 HEAD 的指向不应该发生改变),直接将指定快照的指定文件回滚到暂存区域。

    不仅可以往回滚,还可以往前滚!
    这里需要强调的是:reset 不仅是一个“复古”的命令,它不仅可以回到过去,还可以去到“未来”。

    唯一的一个前提条件是:你需要知道指定快照的 ID 号。

    那如果不小心把命令窗口关了不记得ID号怎么办?
    命令:git reflog
    Git记录的每一次操作的版本ID号

    比较暂存区域与工作目录

    直接执行 git diff 命令是比较暂存区域与工作目录的文件内容:

    这里可能出现一个问题,直接执行的结果出现中文乱码。在cmd界面的冒号:后面输入q退出,使用Notepad++打开README文件,点击编码→转为UTF-8编码。(旧版本中选择UTF-8(无BOM),新版中的UTF-8默认为无BOM)重新执行git diff发现还是不行!怎么肥四??在本菜查遍各网站论坛之后,终于找到了解决方法
    执行以下三条命令(别问我明明是四条为啥说三条...)

    git config --global i18n.commitencoding utf-8
    git config --global i18n.logoutputencoding utf-8
    
    export LESSCHARSET=utf-8 ## linux bash配置环境变量
    set LESSCHARSET=utf-8 #windows配置环境变量
    

    比较两个历史快照

    我们执行 git commit -am "添加功能:玩家只有三次机会" 命令,添加并提交工作目录中的所有文件。执行 git log 命令,可以看到现在 Git 仓库中已经有两个快照了:

     执行 git diff 6e26975 ed3708c 命令,即可比较 Git 仓库中两个快照的差异:

    比较之前版本的快照与当前工作目录内容
    输入 git diff ed3708c 命令即可

    比较当前版本快照与当前工作目录内容
    输入 git diff HEAD 命令即可

    Git使用教程7---修改最后一次提交、删除文件和重命名文件

    由于使用reset命令过于繁琐,需要提交一个新的版本,这里可以使用带 --amend 选项的 commit 命令,(即git commit --amend)Git 会“更正”最近的一次提交。由于这里没有-m说明,
    如果不需要修改,可以连续按下两个大写Z来退出,或者按下(:)再输入q!退出,Git会保留旧的提交说明。如果需要提交说明又不想用这么繁琐的方式,输入git commit --ammend -m “新的提交说明” 即可。

    删除文件

    问题一:不小心删除文件怎么办?
    现在从工作目录中手动删除 README.md 文件,然后执行 git status 命令:

    提醒使用 checkout 命令可以将暂存区域的文件恢复到工作目录:

    文件就会重新返回。
    问题二:那么如何彻底删除一个文件呢?
    假如你不小心把小黄图下载到了工作目录,然后又不小心提交到了 Git 仓库:

    执行 git rm yellow.jpg 命令:

    此时工作目录中的小黄图(yellow.jpg)已经被删除……
    但执行 git status 命令,你仍然发现 Git 还不肯松手:

    意思是说它在仓库的快照中发现有个叫 yellow 的东西,但似乎在暂存区域和当前目录不见了!

    此时可以执行 git reset --soft HEAD~ 命令将快照回滚到上一个位置,然后重新提交,Git 就不会再提小黄图的事儿了:

    注意:rm 命令删除的只是工作目录和暂存区域的文件(即取消跟踪,在下次提交时不纳入版本管理)

    问题三:我在工作目录中增加一个 test.py 文件,然后执行 git add test.py 命令将其添加到暂存区域,此时我修改 test.py 文件的内容,那么暂存区域和工作目录就是两个不同的 test.py 文件了,此时如果我执行 git rm test.py 命令,Git 会下意识地阻止我,这是怎么办?

    因为两个不同内容的同名文件,谁知道你是不是搞清楚了都要删掉?还是提醒一下好,别等一下出错了又要赖机器……
    根据提示,执行 git rm -f test.py 命令就可以把两个都删除。

    问题四:我只想删除暂存区域的文件,保留工作目录的,应该怎么操作?
    执行 git rm --cached 文件名 命令。

    重命名文件

    直接在工作目录重命名文件,执行git status出现错误:

    正确的姿势应该是:

    git mv 旧文件名 新文件名

    注:Windows 使用 ren 命令修改文件名,Linux 是使用 mv 命令

    教程6彩蛋

    如何让Git 识别某些格式的文件,然后自主不跟踪它们?
    比如工作目录中有三个文件1.temp、2.temp 和 3.temp,我们不希望后缀名为 temp 的文件被追踪,可是每次执行git status都会出现:

    解决办法:在工作目录创建一个名为 .gitignore 的文件。

    然后你发现 Windows 压根儿不允许你在文件管理器中创建以点(.)开头的文件。windows需要在命令行窗口创建(.)开头的文件。执行 echo *.temp > .gitignore 命令,创建一个 .gitignore 文件,并让 Git 忽略所有 .temp 后缀的文件:

    好了,Git 已经忽略了所有的 *.temp 文件(你还可以把 .gitignore 文件也一并忽略)。

    Git使用教程7---创建和切换分支

    分支是什么?

    假设你的大项目已经上线了(有上百万人在使用),过了一段时间你突然觉得应该添加一些新的功能,但是为了保险起见,你肯定不能在当前项目上直接进行开发,这时候你就有创建分支的需要了。

    对于其它版本控制系统而言,创建分支常常需要完全创建一个源代码目录的副本,项目越大,耗费的时间就越多;而 Git 由于每一个结点都已经是一个完整的项目,所以只需要创建多一个“指针”(像 master)指向分支开始的位置即可。

    创建分支

    来到之前创建的项目MyProject2,

    目前仓库的状态如下:

    执行git status查看状态:

    可以看到 README.md 文件被修改并添加到暂存区域(还没有提交),所以当前三棵树应该是这样:

    创建分支,使用 git branch 分支名 命令:

    没有任何提示说明分支创建成功(一般也不会失败啦,除非创建了同名的分支会提醒你一下),此时可以执行 git log --decorate 命令查看:

    如果希望以“精简版”的方式显示,可以加上一个 --oneline 选项(即 git log --decorate --oneline),这样就只用一行来显示一个快照记录。

    可以看到最新的快照后边多了一个 (HEAD -> master, feature)

    它的意思是:目前有两个分支,一个是主分支(master),一个是刚才我们创建的新分支(feature),然后 HEAD 指针仍然指向默认的 master 分支。

    所以目前仓库中的快照应该是这样:


    切换分支

    现在我们需要将工作环境切换到新创建的分支(feature)上,使用的就是之前我们欲言又止的 checkout 命令。执行 git checkout feature 命令:

    这样 HEAD 指针就指向 feature 分支了:

    现在我们进行一次提交(暂存区域还有一个更改的文件没有提交呢):

    现在仓库中的快照应该是酱紫(提交的快照由当前HEAD指针指向的分支来管理):

    然后我们将 HEAD 指针切回 master 分支:

    细心的朋友会发现上一次对 README.md 文件的修改已经荡然无存了,这是因为我们的工作目录已经回到 master 分支的状态中:

    现在对 README.md 文件进行修改(随便改改),然后执行 git commit -m "再次修改说明文件":

    目前仓库中的快照应该变成了酱紫:

    执行 git log --oneline --decorate --graph --all 命令:

    --graph 选项表示让 Git 绘制分支图,--all 表示显示所有分支

    Git使用教程9---合并和删除分支

    合并分支

    当一个子分支的使命完结之后,它就应该回归到主分支中去。

    合并分支我们使用 merge 命令,执行 git merge feature 命令,将 feature 分支合并到 HEAD 所在的分支(master)上:

    从 Git 提示的内容来看,我们知道这次的合并并没有成功,Git 说:

    合并 README.md 文件的时候出现冲突。

    所以自动合并失败;请修改冲突的内容并重新提交快照。

    意思是说现在你需要先解决冲突的问题,Git 才能进行合并操作。所谓冲突,无非就是像两个分支中存在同名但内容却不同的文件,Git 不知道你要舍弃哪一个或保留哪一个,所以需要你自己来决定。
    此时执行 git status 命令也会显示需要你解决的冲突:

    然后 Git 会在有冲突的文件中加入一些标记,不信你打开 README.md 文件看看:

    以“=======”为界,上到“<<<<<<< HEAD”的内容表示当前分支,下到“>>>>>>> feature”表示待合并的 feature 分支,之间的内容就是冲突的地方。

    现在我们将 README.md 统一修改(去掉 <<<<<<< HEAD 等内容)
    保存文件,然后提交快照:

    执行 git log --decorate --all --graph --oneline 命令,可以看到此时的分支已经自动合并了:

    当然,如果不存在冲突,就不用搞这么多了……举个例子:
    执行 git checkout -b feature2 命令(相当于 git branch feature2 和 git checkout feature2 两个命令的合体):

    在工作目录随便创建一个文本文件(feature2.txt)并提交快照:

    执行 git log --decorate --all --graph --oneline 命令:

    可以看到,feature2 分支比 master 分支快了一步。现在我们切换回 master 分支,并将 feature2 分支合并进来:

    这次 Git 只显示了 Fast-forward(快进)这词儿,这是因为 feature2 这个分支的父结点是 master 分支,所以 Git 只需要简单移动 master 的指向即可。

    执行 git log --decorate --all --graph --oneline 命令:

    删除分支

    删除分支,使用 git branch -d 分支名 命令:

    执行 git log --decorate --all --graph --oneline 命令:

    由于 Git 的分支原理实际上只是通过一个指针记载,所以创建和删除分支都几乎是瞬间完成。

    注意:如果试图删除未合并的分支,Git 会提示你“该分支未完全合并,如果你确定要删除,请使用 git branch -D 分支名 命令。

    彩蛋:Git的两种合并方式 --- Fast-forward 和 Three-way merge

    Fast-forward

    所谓的 Fast-forward 就是当待合并的分支位于目标分支的直接上游时,Git 只需把目标分支的指针直接移动即可实现合并。

    比如下面图片中 master 分支是位于 feature2 分支的直接上游:

    将 feature2 分支合并到 master 分支,只需要移动 master 的指针即可:

    Three-way merge

    如果待合并的两个分支不在同一条线上,那么进行合并就需要解决一个根本的问题 —— 冲突!

    为何两个分支在同一条线上就不会冲突呢?

    因为 Git 的快照是按时间顺序提交的,所以在同一条线上的两个快照,它们是有先后顺序的,尽管两者可能出现同名文件不同内容,Git 会认为这是“改变”而不是“冲突”。

    举个例子:

    合并 C3 和 C4 得到 C5,但 C5 应该如何处理“冲突”呢?

    SVN 会把问题抛给用户,让用户自行解决;Git 则显得更为高明,它会找到第三个快照,然后综合三者特点自动解决冲突。

    那第三个快照应该如何决定呢?

    没错,应该找两者的共同“祖先”作为参照物,一比较就知道两个分支都干了些什么。

    图片中 C3 和 C4 的共同祖先是 C1,可以看到 C3 和 C4 分别增加了 test2.py 和 test1.py 两个文件。因为对比之后发现三者并没有冲突,所以 C5 应该是三者的合体,即同时拥有 common.py、test1.py 和 test2.py 三个文件。

    另外,值得一提的是,Git 这种合并方式也适用于同名文件的不同更改

    举个例子:

    这里 C3 和 C4 都只有一个文件(test.txt),但是内容却不一样。如果这样合并,你猜 Git 会不会报“冲突”?

    答案是不会的!

    因为 Git 找到它们的共同祖先 C1,可以看到 C3 和 C4 都是在 C1 的基础上进行添加(C4 在第 2 行添加了“I”,C3 在第 4 行增加了“FishC”,C1 第 3 行的“love”是它们共同拥有的),同时在每一行并没有产生冲突的地方,所以自动合并后的 C5 是这样的:

    # test.txt
    I
    love
    FishC
    

    注意:如果 Git 检测到同一行有不同的内容,还是会报冲突并让你自行决定谁去谁留的!

    Git使用教程10---匿名分支和checkout命令

    匿名分支

    创建一个新的文件夹(MyProject3),然后初始化 git。依次创建三个文件并提交(每创建一个文件提交一次):

    上一节课我们讲的是使用 branch 命令创建一个分支,然后使用 checkout 命令切换分支。

    如果在没创建分支的情况下执行 checkout 命令,会有怎样的事情发生呢?

    我们不妨试试看,执行 git checkout HEAD~ 命令:

    当前的 HEAD 指针处于分离状态,你可以环顾四周,做一些实验性修改并提交它们,并且你可以在这个状态中丢弃任何你所做的提交,而不影响任何分支,做法是执行 checkout 命令切换回别的分支。

    如果你希望创建一个新分支,并保持你所做创建的提交,你可以(现在或稍后)通过使用带有 -b 选项的 checkout 命令实现。例如:

    git checkout -b <new-branch-name>

    HEAD 指针当前指向 52861cf... 2.txt

    你使用了 checkout 命令但没有指定分支名,所以 Git 帮你创建了一个匿名分支,OK,既然是匿名,那么当你切换到别的分支时,这个匿名分支中的所有提交都会被丢弃掉(因为你都没给人家命名,反正以后都找不回了,不丢了干啥?)。因此,你可以利用匿名分支来做做实验什么的,反正不会有负面影响。

    来,我们试试,在工作目录中创建一个 4.txt(你会发现 3.txt 不见了,这是因为 checkout 将环境切换到上一次提交了),然后提交

    执行 git log --decorate --all --graph --oneline 命令

    可以看到有两个分支,但 HEAD 所在的分支并没有名字(匿名分支),那现在我们把 HEAD 切回 master 分支:

    警告:你残留一个没有连接任何分支的提交:

    178d909 4.txt

    如果你想通过创建一个分支来连接它,这将是一个好时机,请执行:

    git branch <new-branch-name> 178d909

    已经切换到 'master' 分支

    现在再来查看提交日志,可以看到匿名分支已经荡然无存:

    再论checkout

    事实上呢,checkout 命令有两种功能:

    1. 从历史快照(或者暂存区域)中拷贝文件到工作目录
    2. 切换分支

    从历史快照(或者暂存区域)中拷贝文件到工作目录

    当给定某个文件名时,Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行 git checkout HEAD~ README.md 命令会将上一个快照中的 README.md 文件复制到工作目录和暂存区域中:

    如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录(git checkout README.md):

    有些朋友可能会问:“上次看你在文件名的前边有加两个横杆(--),这次怎么就没有了呢?”

    问得好,Git 提醒你写成 git checkout -- README.md 的形式,那是为了预防你恰好有一个分支叫做 README.md,那么它就搞不懂你要恢复文件还是切换分支了,所以约定两个横杆(--)后边跟的是文件名。

    反过来说,如果你确保你没有一个叫做 README.md 的分支,你直接写 git checkout README.md 也是妥妥的没问题啦

    切换分支
    首先我们知道 Git 的分支其实就是添加一个指向快照的指针,其次我们还知道切换分支除了修改 HEAD 指针的指向,还会改变暂存区域和工作目录的内容。

    所以执行 git checkout 373c0 命令,Git 主要就是做了下边这两件事(当然事实上 Git 还做了更多):

    那回过头来,如果我们只想恢复指定的文件/路径,那么我们只需要指定具体的文件,Git 就会忽略第一步修改 HEAD 指向的操作,这不正跟之前讲 reset 命令的时候一样吗?

    checkout 命令和 reset 命令的区别

    恢复文件

    checkout 命令和 reset 命令都可以用于恢复指定快照的指定文件,并且它们都不会改变 HEAD 指针的指向。

    下面开始划重点:

    它们的区别是 reset 命令只将指定文件恢复到暂存区域(--mixed),而 checkout 命令是同时覆盖暂存区域和工作目录。

    注意:也许你试图使用 git reset --hard HEAD~ README.md 命令让 reset 同时覆盖工作目录,但 Git 会告诉你这是徒劳(此时 reset 不允许使用 --soft 或 --hard 选项)。

    这样看来,在恢复文件方面,reset 命令要比 checkout 命令更安全一些。

    恢复快照

    reset 命令是用来“回到过去”的,根据选项的不同,reset 命令将移动 HEAD 指针(--soft) -> 覆盖暂存区域(--mixed,默认)-> 覆盖工作目录(--hard)。

    checkout 命令虽说是用于切换分支,但前面你也看到了,它事实上也是通过移动 HEAD 指针和覆盖暂存区域、工作目录来实现的。

    那问题来了:它们有什么区别呢?

    下面开始划重点:

    第一个区别是,对于 reset --hard 命令来说,checkout 命令更安全。因为 checkout 命令在切换分支前会先检查一下当前的工作状态,如果不是“clean”的话,Git 不会允许你这样做;而 reset --hard 命令则是直接覆盖所有数据。

    另一个区别是如何更新 HEAD 指向,reset 命令会移动 HEAD 所在分支的指向,而 checkout 命令只会移动 HEAD 自身来指向另一个分支。

    看文字你肯定懵,我们举例说明。

    来,大家先把刚才的例子改成下边这样:

    执行 git checkout feature 命令:

    可以看到只是 HEAD 指针跑到 feature 分支那儿去了。

    好,我们执行 git checkout master 命令将其切回。

    现在执行 git reset --hard feature 命令:

    彩蛋

    通常情况下,Git 会尽可能地尝试使用 Fast-forward 方式来合并分支,因为这样效率非常高,只有在万不得已的时候才使用三方合并(Three-way merge)

    但是,有时候 Fast-forward 的方式却很容易让我们忽略了分支的存在!

    举个例子,比如下面这样:

    如果我们把“feature”分支删除,就会直接丢掉分支的信息:

    根本就不知道有个分支存在过……

    可有时候我们确实希望保留分支的信息,应该怎么办呢?

    只需要在 merge 的时候使用 --no-ff 选项即可告诉 Git 不要使用 Fast-forward 方式合并分支。

    这样 Git 就会乖乖地使用三方合并(Three-way merge):

    OK,这样就算删掉了“feature”分支,我们仍然可以很容易看出有个分支曾经存在过:

    作者:spectre_hola
    链接:https://www.jianshu.com/p/e57a4a2cf077
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     
  • 相关阅读:
    django框架——十二
    django框架——十一
    请简述一下你所了解的数据源控件有哪些
    在ASP.NET中,<%= %>和<%# %>有什么区别
    请解释ASP.NET中的web页面与其隐藏类之间的关系
    什么是viewstate,能否禁用?是否所用控件都可以禁用
    WEB控件及HTML服务端控件能否调用客户端方法?如果能,请解释如何调用
    静态类和静态方法的好处
    请写出在ASP.NET中常用的几种页面间传值的方法,并说出它们的特点。
    连接数据库主要有哪几个对象
  • 原文地址:https://www.cnblogs.com/luyuefei/p/13392022.html
Copyright © 2011-2022 走看看