作者:Rhythm-2019
邮箱:rhythm_2019@163.com
最近更新:2020.01.03

感觉如同两三个月没写博客了,最近始终要去实验室做毕设,之前在Gitee上看见一个我的项目Learn Git Branching,是一个可视化的Git学习平台。所以除夕找了两天来学习一下。尽管感觉当前工作可能面对的问题会更简单一些,也没有说教程外面这么直观,然而打好根底嘛,大家也能够去体验一下

根底指令

  • git commit

    比照新旧仓库文件的内容产生一份提交记录,新的提交记录指向旧的提交记录

  • git branch

    在以后最新提交记录中创立一个新的正本,以新的名称命名

  • git checkout

    用于切换分支,git checkout -b能够创立并切换到新的分支

  • git marge <援用>

    以后分支和新分支合并,在以后分支上产生一个提交记录,该提交记录指向两个分支的上一个节点

    因为以后master上蕴含了所有的提交,再次合并Git什么都不会做

  • git rebase

    让两个分支合体,让其看上去像是线性开发的(实际上是并行的)

留神,git rebase <ref>是将HEAD指向记录及其之前的记录复制到ref指定地位上

操作分支

上面介绍一些分支上的操作

HEAD

咱们首先看一下 “HEAD”。 HEAD 是一个对以后检出记录的符号援用 —— 也就是指向你正在其根底上进行工作的提交记录。

HEAD 总是指向以后分支上最近一次提交记录。大多数批改提交树的 Git 命令都是从扭转 HEAD 的指向开始的。

HEAD 通常状况下是指向分支名的(如 bugFix)。在你提交时,扭转了 bugFix 的状态,这一变动通过 HEAD 变得可见。
拆散的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:

HEAD -> master -> C1

HEAD 指向 master, master 指向 C1

输出git checkout C1

HEAD -> C1

对于不同的提交记录,咱们能够通过git log晓得他的哈希值,而后应用git checkout指向后进行操作AD

集体对HEAD和分支的了解:我感觉他们都像是一个指针,他们都能够指向提交记录,然而HEAD甚至能够指向分支,咱们能够应用git checkout <分支>对HEAD进行拆散,拆散后分支就不随着HEAD的挪动而挪动了,包含提交挪动

绝对援用

咱们应用git log会查到每次提交的哈希值,因为哈希值比拟长,如果咱们向疾速让HEAD指向上一次或几次提交,能够间接应用上面两个操作符号

  • ^ 上一个父节点(如果有两个父节点请应用^1、^2来示意)
  • ~ 上几个父节点,如上两个父节点能够应用~2示意

这两个符号反对连锁操作

操作分支

咱们当初能够应用checkout轻松操作HEAD了,咱们同样能够应用git branch -f <分支> <提交记录>,让某个分支回到某个记录上,例如上面的练习,操作左边的HEAD和分支是的他变成右边红色底色的模样

我的答案是

git branch -f master C6git checkout HEAD^git branch -f bugFix HEAD^

撤销分支

如果在本地,咱们能够应用git reset <指标提交记录>对以后提交记录的下一个记录及前面的所有记录进行撤回操作,如果你须要对近程仓库进行操作,则须要应用git revert进行撤销,撤销后会产生一个新的提交记录便于你进行提交

大家能够从上面的形容中看出两者区别

大家要留神HEAD的地位,reset后的参数是指指标地位

总结一下就是reset只对本地进行撤销,revert针对近程仓库进行撤销

挪动提交记录

应用git charry-pick <记录1> <记录2>...能够疾速将提交记录复制到以后分支地位

当然啦,当你须要复制的记录比拟多,你能够应用交互式的rebase实现,指令为git rebase -i <指标援用>,Git会弹出一个抉择窗口,他会让你编辑以后HEAD指向及以前的记录供你进行编辑,编辑好后帮你复制到指标援用前面

当你的我的项目呈现了BUG你想要把他修复,你在代码外面加了很多输入语句,提交了一次记录,批改好BUG在提交一次。显然你是心愿将第二次提交放入master,这时就须要应用git cherry-pickgit rebase -i

咱们总结一下rebase的用法吧:

  • git rebase <ref> 将以后的HEAD指向的提交记录(蕴含之前的记录)复制到ref前面
  • git rebase <to> <from>form指向的记录(包含之前的)复制到to前面
  • git rebase -i <ref> 与第一个指令一样,只是提供了UI界面能够删除两头的某些记录

实战练习

对于咱们刚刚学习的两个指令

  • git cherry-pick <record...>
  • git rebase -i <record>

在配合上咱们之前学习的

  • git checkout <record>
  • git branch -f <分支> <record>

咱们能够轻松的实现所有的提交记录变更

练习1

例如上面这个练习,在咱们开发中也很常见,就是程序员1实现了图片代码编写并创立newImage分支提交了本人的代码,程序员2在newImage分支根底上创立了新的分支caption并提交了本人新的代码,当初主管感觉程序员1的代码写的有问题,须要进行批改并整合程序员2的代码

所以我的指令是

git rebase -i master # 调整C2 C3的程序使得C2是最新的
git commit --amend   # 更新C2
git rebase -i master # 将C2 C3调整回来
git branch -f master caption # 让master指向caption的指向

如果程序员1和程序员2开发不同的模块,这样调整没什么问题,然而如果他们对同一个代码进行了批改可能会造成代码抵触

更好的应该是应用cherry-pick,指令如下

git checkout master # 让HEAD指向maser指向的记录git cherry-pcik newImage # 复制newImage到mastergit commit --amend # 更新newImagegit cherry-pick caption # 复制caption

你会发现应用cherry-pick后,分支的指向都会及时更新

练习2

再如须要你合并上面所有分支的内容

答案是

git rebase master bugFixgit rebase bugFix sidegit rebase side another git rebase naster another  # 更新master到最新

练习3

产生上面三个分支

治理只能应用cherry-pick复制了,答案是:

git checkout onegit cherry-pick C4 C3 C2git checkout twogit cherry-pick C5 C4 C3 C2git branch -f three C2

里程碑

你会发现分支和HEAD都会随着提交而挪动,当我的项目做到肯定水平要发一个大版本的时候吗,你心愿用一个标签示意这个大版本的提交记录的话,能够应用git tag <标签> <援用>来标识,该标签永远指向该提交记录,因而被称为里程碑

Git还提供了一个指令git describe <ref>,用于查问间隔该提交最近的里程碑和间隔他的步长

近程仓库

因为咱们当初须要进行合作开发,所以代码须要放在仓库进行治理,近程仓库有上面两个特点,我间接援用教程的话啦

  • 首先也是最重要的的点, 近程仓库是一个弱小的备份。本地仓库也有复原文件到指定版本的能力, 但所有的信息都是保留在本地的。有了近程仓库当前,即便失落了本地所有数据, 你仍能够通过近程仓库拿回你失落的数据。
  • 还有就是, 近程让代码社交化了! 既然你的我的项目被托管到别的中央了, 你的敌人能够更容易地为你的我的项目做奉献(或者拉取最新的变更)

克隆我的项目

咱们能够应用git clone url克隆一个我的项目

近程分支

与本地分支不同,近程分支个别以<remote_name><branch_name>命名,remote_name个别是origin示意

当你应用git checkout o/master的时候会主动拆散出HEAD,对于本地分支则会让HEAD指向master,这是对近程分支的一种爱护,即近程分支不能被挪动

近程分支反映了近程仓库在你最初一次与它通信时的状态,咱们能够从近程仓库中获取数据或提交数据

获取数据

咱们能够应用git fetch获取最新的仓库,fetch会帮忙咱们实现两件事

  1. 从近程仓库下载本地仓库中缺失的提交记录
  2. 更新近程分支指针(如 o/master)

聪慧的你可能以及发现了本地分支master没有更新,fetch只会更新近程分支

这其实十分常见,比方我写某局部代码写了比拟久,共事在我提交之前提交了更新的代码,那我应该这样做

  • git fetch 更新o/master分支内容
  • git merge o/master 将最新代码合并到以后我本地的最新提交中

大家能够看上面两幅图,图一是还没输出指令之前

执行后

其实Git提供了pull指令就是合并了这两条指令

提交代码

咱们能够应用git push提交你的代码,代码同步实现后,近程分支会自动更新到最新状态

然而个别状况是你上传代码时发现同时比你先提交但你又没及时拉下最新的代码,咱们须要先将把最新的代码拉下来,而后调整一下程序

git fetch
git rebase o/master

如果你只是简答的应用git pull,再push的话成果如下

这样近程仓库的代码记录会比拟乱,所以大家还是先应用git fetch来下最新的代码,而后应用rebase调整程序后再push,其中

git fetch
git rebase o/master

能够简写成git pull --rebase

例如这里须要你合并所有的分支并提交

咱们只须要应用rebase合并就好

git fetchgit rebase o/master side1git rebase side1 side2git rebase side2 side3git rebase side3 mastergit push

有同学可能会问能不能应用merge来调整rebase,其实必定是能够的,rebase有本人的优缺点

  • 长处:线性整洁
  • 毛病:批改了提交程序

push 有里两个参数,第一个是remote的名称,默认origin,第二个是你须要提交的分支名称,你肯定见过这个

git push origin master

把这个命令翻译过去就是:

切到本地仓库中的“master”分支,获取所有的提交,再到近程仓库“origin”中找到“master”分支,将近程仓库中没有的提交记录都增加下来,搞定之后通知我。

Git还提供设置提交映射的形式,girt push orgin <本地>:<近程>,这样咱们能够将本人的分支间接提交到master下面

其实git fetch也有相似的性能,git fetch origin <近程>:<本地>能够指定跟新哪个分支

留神:如果你应用git fetch origin master这种写法挪动的是近程分支o/master,如果你应用的是 `git fetch origin <近程>:<本地>的话挪动的是本地分支

git pull也有相似的性能,大家能够去摸索一下

这两个命令还有两个非凡用法:

git psuh origin :分支 # 删除本地和近程分支git fetch origin :分支 # 创立本地分支

近程跟踪

其实我也在好奇Git怎么就晓得master对应o/master的呢?原来是你执行git clone的时候就曾经默认绑定了,也就是本地分支master跟踪近程分支o/master。咱们有没有方法创立本人的分支,让本人的分支也跟着o/master呢?

  • git checkout -b <新分支> o/master
  • git branch -u o/master <新分支>

删除文件

平时我大手大脚的不小心把一些不该提交的货色提交了该怎么办

  • 如果你只是应用git add退出了暂存区,你能够应用git rm及时删除文件
  • 如果你曾经commit了,你须要撤销这次commit,这个上面讲
  • 如果你曾经push了,则须要执行上面命令

    git rm -r --cached a/2.txt //删除a目录下的2.txt文件 删除a目录git rm -r --cached a
    git commit -m "删除a目录下的2.txt文件"

    用-r参数删除目录,git rm --cached a.txt删除的是本地仓库中的文件,且本地工作区的文件会保留且不再与近程仓库产生跟踪关系,如果本地仓库中的文件也要删除则用git rm a.txt

撤销文件操作

这路分几种状况哈

  1. 当你在工作区批改了某个文件,而后忽然想撤回到刚拉下来的时候的墨阳

    git checkout -- filename

  2. 如果你批改文件后add到暂存区了须要撤回到最后的样子

    git reset HEAD filename

  3. 当初你曾经commit了,但你想回去

    依据下面所学,这里能够间接撤销这次提交,而后再从暂存区中撤回,所以命令是

    git reset --hard filename

  4. 曾经push

    git revert HEAD^

  5. 撤回完悔恨了,又想回去

    git reflag # 查出刚刚指向指令的coomitId
    git reset -hard <commit_id>

值得一提的是commit -a能够间接将这次提交追加到上一次中

参考

  • Git指令和办法大全:https://www.cnblogs.com/miracle77hp/articles/11163532.html
  • Learn Git Branching:https://oschina.gitee.io/learn-git-branching/