Git 不要只会 pull 和 push,试试这 5 条提高效率的命令

Git 不要只会 pull 和 push,试试这 5 条提高效率的命令,第1张

使用 Git 作为代码版本管理,早已是现在开发工程师必备的技能。可大多数工程师还是只会最基本的保存、拉取、推送,遇到一些commit管理的问题就束手无策,或者用一些不优雅的方式解决。

本文分享我在开发工作中实践过的实用命令。这些都能够大大提高工作效率,还能解决不少疑难场景。下面会介绍命令,列出应用场景,手摸手教学使用,让同学们看完即学会。

官方解释:当您想记录工作目录和索引的当前状态,但又想返回一个干净的工作目录时,请使用git stash。该命令将保存本地修改,并恢复工作目录以匹配头部提交。

stash 命令能够将还未 commit 的代码存起来,让你的工作目录变得干净。

我猜你心里一定在想:为什么要变干净?

应用场景:某一天你正在 feature 分支开发新需求,突然产品经理跑过来说线上有bug,必须马上修复。而此时你的功能开发到一半,于是你急忙想切到 master 分支,然后你就会看到以下报错:

因为当前有文件更改了,需要提交commit保持工作区干净才能切分支。由于情况紧急,你只有急忙 commit 上去,commit 信息也随便写了个“暂存代码”,于是该分支提交记录就留了一条黑 历史 …(真人真事,看过这种提交)

如果你学会 stash,就不用那么狼狈了。你只需要:

就这么简单,代码就被存起来了。

当你修复完线上问题,切回 feature 分支,想恢复代码也只需要:

当有多条 stash,可以指定 *** 作stash,首先使用stash list 列出所有记录:

应用第二条记录:

pop,drop 同理。

stash 代码

填写备注内容,也可以不填直接Enter

在STASHES菜单中可以看到保存的stash

先点击stash记录旁的小箭头,再点击 apply 或者 pop 都可恢复 stash

完全不接触索引文件或工作树(但会像所有模式一样,将头部重置为)。这使您的所有更改的文件更改为“要提交的更改”。

回退你已提交的 commit,并将 commit 的修改内容放回到暂存区。

一般我们在使用 reset 命令时, git reset --hard 会被提及的比较多,它能让 commit 记录强制回溯到某一个节点。而 git reset --soft 的作用正如其名, --soft (柔软的) 除了回溯节点外,还会保留节点的修改内容。

回溯节点,为什么要保留修改内容?

应用场景1:有时候手滑不小心把不该提交的内容 commit 了,这时想改回来,只能再 commit 一次,又多一条“黑 历史 ”。

应用场景2:规范些的团队,一般对于 commit 的内容要求职责明确,颗粒度要细,便于后续出现问题排查。本来属于两块不同功能的修改,一起 commit 上去,这种就属于不规范。这次恰好又手滑了,一次性 commit 上去。

学会 reset --soft 之后,你只需要:

reset --soft 相当于后悔药,给你重新改过的机会。对于上面的场景,就可以再次修改重新提交,保持干净的 commit 记录。

以上说的是还未 push 的commit。对于已经 push 的 commit,也可以使用该命令,不过再次 push 时,由于远程分支和本地分支有差异,需要强制推送 git push -f 来覆盖被 reset 的 commit。

还有一点需要注意,在 reset --soft 指定 commit 号时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit。

举个例子:

commit 记录有 c、b、a。

reset 到 a。

此时的 HEAD 到了 a,而 b、c 的修改内容都回到了暂存区。

给定一个或多个现有提交,应用每个提交引入的更改,为每个提交记录一个新的提交。这需要您的工作树清洁(没有从头提交的修改)。

将已经提交的 commit,复制出新的 commit 应用到分支里

commit 都提交了,为什么还要复制新的出来?

应用场景1:有时候版本的一些优化需求开发到一半,可能其中某一个开发完的需求要临时上,或者某些原因导致待开发的需求卡住了已开发完成的需求上线。这时候就需要把 commit 抽出来,单独处理。

应用场景2:有时候开发分支中的代码记录被污染了,导致开发分支合到线上分支有问题,这时就需要拉一条干净的开发分支,再从旧的开发分支中,把 commit 复制到新分支。

复制单个

现在有一条feature分支,commit 记录如下:

需要把 b 复制到另一个分支,首先把 commitHash 复制下来,然后切到 master 分支。

当前 master 最新的记录是 a,使用 cherry-pick 把 b 应用到当前分支。

完成后看下最新的 log,b 已经应用到 master,作为最新的 commit 了。可以看到 commitHash 和之前的不一样,但是提交时间还是保留之前的。微信搜索公众号:Java后端编程,回复:java 领取资料 。

复制多个

以上是单个 commit 的复制,下面再来看看 cherry-pick 多个 commit 要如何 *** 作。

上面的命令将 commit1 和 commit2 两个提交应用到当前分支。

上面的命令将 commit1 到 commit2 这个区间的 commit 都应用到当前分支(包含commit1、commit2),commit1 是最早的提交。

在 cherry-pick 多个commit时,可能会遇到代码冲突,这时 cherry-pick 会停下来,让用户决定如何继续 *** 作。下面看看怎么解决这种场景。

还是 feature 分支,现在需要把 c、d、e 都复制到 master 分支上。先把起点c和终点e的 commitHash 记下来。

切到 master 分支,使用区间的 cherry-pick 。可以看到 c 被成功复制,当进行到 d 时,发现代码冲突, cherry-pick 中断了。这时需要解决代码冲突,重新提交到暂存区。

然后使用 cherry-pick --continue 让 cherry-pick 继续进行下去。最后 e 也被复制进来,整个流程就完成了。

以上是完整的流程,但有时候可能需要在代码冲突后,放弃或者退出流程:

回到 *** 作前的样子,就像什么都没发生过。

不回到 *** 作前的样子。即保留已经 cherry-pick 成功的 commit,并退出 cherry-pick 流程。

给定一个或多个现有提交,恢复相关提交引入的更改,并记录一些这些更改的新提交。这就要求你的工作树是干净的(没有来自头部的修改)。

将现有的提交还原,恢复提交的内容,并生成一条还原记录。

应用场景:有一天测试突然跟你说,你开发上线的功能有问题,需要马上撤回,否则会影响到系统使用。这时可能会想到用 reset 回退,可是你看了看分支上最新的提交还有其他同事的代码,用 reset 会把这部分代码也撤回了。由于情况紧急,又想不到好方法,还是任性的使用 reset,然后再让同事把他的代码合一遍(同事听到想打人),于是你的技术形象在同事眼里一落千丈。

revert 普通提交

学会 revert 之后,立马就可以拯救这种尴尬的情况。

现在 master 记录如下:

revert 掉自己提交的 commit。

因为 revert 会生成一条新的提交记录,这时会让你编辑提交信息,编辑完后 :wq 保存退出就好了。

再来看下最新的 log,生成了一条 revert 记录,虽然自己之前的提交记录还是会保留着,但你修改的代码内容已经被撤回了。

在 git 的 commit 记录里,还有一种类型是合并提交,想要 revert 合并提交,使用上会有些不一样。

现在的 master 分支里多了条合并提交。

使用刚刚同样的 revert 方法,会发现命令行报错了。为什么会这样?在官方文档中有解释。

通常无法 revert 合并,因为您不知道合并的哪一侧应被视为主线。此选项指定主线的父编号(从1开始),并允许 revert 反转相对于指定父编号的更改

我的理解是因为合并提交是两条分支的交集节点,而 git 不知道需要撤销的哪一条分支,需要添加参数 -m 指定主线分支,保留主线分支的代码,另一条则被撤销。

-m 后面要跟一个 parent number 标识出"主线",一般使用 1 保留主分支代码。

还是上面的场景,在 master 分支 revert 合并提交后,然后切到 feature 分支修复好 bug,再合并到 master 分支时,会发现之前被 revert 的修改内容没有重新合并进来。

因为使用 revert 后, feature 分支的 commit 还是会保留在 master 分支的记录中,当你再次合并进去时,git 判断有相同的 commitHash,就忽略了相关 commit 修改的内容。

这时就需要 revert 掉之前 revert 的合并提交,有点拗口,接下来看 *** 作吧。

现在 master 的记录是这样的。

再次使用 revert,之前被 revert 的修改内容就又回来了。

此命令管理重录中记录的信息。

如果说 reset --soft 是后悔药,那 reflog 就是强力后悔药。它记录了所有的 commit *** 作记录,便于错误 *** 作后找回记录。

应用场景:某天你眼花,发现自己在其他人分支提交了代码还推到远程分支,这时因为分支只有你的最新提交,就想着使用 reset --hard ,结果紧张不小心记错了 commitHash,reset 过头,把同事的 commit 搞没了。没办法, reset --hard 是强制回退的,找不到 commitHash 了,只能让同事从本地分支再推一次(同事瞬间拳头就硬了,怎么又是你)。于是,你的技术形象又一落千丈。

分支记录如上,想要 reset 到 b。

误 *** 作 reset 过头,b 没了,最新的只剩下 a。

这时用 git reflog 查看 历史 记录,把错误提交的那次 commitHash 记下。

再次 reset 回去,就会发现 b 回来了。

对我这种喜欢敲命令而不用图形化工具的爱好者来说,设置短命令可以很好的提高效率。下面介绍两种设置短命令的方式。

打开全局配置文件

写入内容

本文主要分享了5个在开发中实用的 Git 命令和设置短命令的方式。

文中列举的应用场景有部分不太恰当,只是想便于同学们理解,最重要的是要理解命令的作用是什么,活学活用才能发挥最大功效。

好啦,今天的分享就到这儿啦,我们下次见啦~

git reset , git checkout ,和 git revert 命令是Git工具箱中最有用的几个工具之一。他们都用来撤销仓库中的某种修改,其中前两个命令可以用来撤销针对提交或者单个文件的修改。

因为如此相似,在特定开发场景下很容易出现不知道该使用那个命令的情况。在本文中我们会比较 git reset , git checkout 和 git revert 命令最常见的使用方式。希望在本文结束时读者能够在自己的项目中胸有成竹地使用对应的命令。
checkout *** 作会将当前 HEAD 指针指向指定的提交。请参见下图:
revert *** 作撤销指定提交并创建一个新的提交,其内容为指定提交的所有逆向修改。 git revert 只能运行在提交层面,不能对指定文件 *** 作。

reset *** 作接受一次commit作为参数,并将git的三棵树状态重置到指定的这次commit的相同状态。reset *** 作可以在三棵树的不同状态下执行。

checkout和reset通常用于本地或者私有分支的撤销 *** 作。修改之后的提交历史,在推送到共享的远程仓库时会引发冲突。反之revert *** 作的“公共撤销”通常被认为是安全的。因为revert *** 作会为撤销动作创建一次提交,而这个撤销历史也会被其他人得到,并且revert *** 作也不会覆盖团队其他成员可能依赖的提交历史。

下表总结了这些命令的常用场景。

向 git reset 和 git checkout 命令传递的参数决定了其影响范围。使用命令时不含文件路径则会让 *** 作作用于整个提交。接下来这部分我们会主要讨论相关内容。注意 git revert 没有文件层面的 *** 作。

在提交层面,重置可以移动分支顶端到其他提交。基于这一特性,重置可以用于删除分支中的提交。比如,下面的命令将 hotfix 分支的顶端向前移动了两个提交。

hotfix 分支的最后两个提交现在称为孤立的提交。这意味着下次Git执行垃圾回收时会删除他们。换句话说,如此 *** 作意味着你要丢弃这些提交。这一过程可以通过下图表示:
除了移动当前分支以外,你还可以传递以下选项,用 git reset 来变更暂存快照或者工作目录:

git checkout 命令用于更新仓库状态到指定的项目提交历史。当传递的参数是一个分支名称,则用于切换分支。

在命令内部,以上所有命令都是移动 HEAD 指针到不同分支,并相应的更新工作目录。由于这一 *** 作具有潜在的覆盖本地变更的可能性,因此Git会强制你在checkout *** 作之前执行commit或者stash命令,以便存储可能由于checkout丢失的变更。与 git reset 不同, git checkout 不会移动分支本身的指针。
revert命令通过新建一个提交来撤销之前的一个提交。因为这一 *** 作不会重写提交历史所以被认为是一种安全的撤销 *** 作。比如下面的例子中,Git会搞清楚倒数第二次提交的内容,然后创建一个新的提交用于撤销这些内容,并且将新提交的撤销动作提交到当前的项目中。

此过程图示如下:
你也可以理解为 git revert 用于撤销已提交的变更, git reset 用于撤销未提交的变更。

与 git checkout 一样, git revert *** 作也会导致潜在的文件覆盖,所以Git也会要求在revert之前先进行commit或者stash *** 作。

git reset 和 git checkout 命令也接受文件路径作为可选参数。这也让其行为与上面所介绍的功能完全不一样。相比于 *** 作整个快照,附加的文件路径参数限制相应 *** 作的影响范围到单个文件。

当附加了文件路径作为参数时, git reset 会根据指定提交更新暂存快照。比如下面的命令会获取 foopy 文件在倒数第二次提交时的快照,根据快照内容变更文件,并暂存它,等待下一次提交:

相比于针对提交的 git reset 命令,上面的命令更多地用于 HEAD 。执行 git reset HEAD foopy 会取消 foopy 的暂存,但其中的改变仍然在工作目录中。
checkout一个文件与使用 git reset 命令传递文件路径类似,除了checkout更新的是工作目录,而不是更新暂存快照。另外,与执行checkout命令关于提交的 *** 作不同,checkout一个提交会改变 HEAD 的指向,而checkout文件不改变 HEAD ,仅改变文件内容。也就意味着执行这个命令不会切换分支。
就像 *** 作提交时使用 git checkout ,这也可以用于查看项目的旧版本——不过这次是查看指定文件的旧版本。

如果你暂存并提交了checkout出来的旧版本文件,其执行结果也含有将指定文件 revert 到旧版本的效果。不过请注意这一 *** 作也同时移除了该文件从旧版本之后的所有后续变更历史,然而 revert 命令仅撤销指定提交的变更。

就像 git reset ,这种情况也通常与 HEAD 搭配使用。比如, git checkout HEAD foopy 执行的结果就含有丢弃 foopy 文件未暂存的变更的效果。这个行为类似于 git reset HEAD --hard ,只不过影响范围仅限于指定文件。

到现在为止,你应该已经拥有用于在Git仓库中撤销变更所需的所有知识了。 git reset , git checkout ,和 git revert 命令容易混淆,但是当你考虑到他们分别在工作目录,暂存快照和提交历史上的可能产生的影响,就不难在开发中分辨出应该使用哪个命令。

原文地址:>

11 配置环境

当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息。该用户信息和GitHub上注册的远程仓库的相关信息没有任何关系。

git config --global username "你的名字"

git config --global useremail "你的邮箱"

git config --list

配置信息保存在用户目录下的giitconfig文件中

12 获取Git仓库

要使用Git对我们的代码进行版本控制,首先需要获得Git仓库

获取Git仓库通常有两种方式:

执行步骤如下:

1、在电脑的任意位置创建一个空目录作为我们的本地Git仓库

2、进入这个目录中,点击右键打开Git bash 窗口

3、执行命令git init

可以通过Git提供的命令从远程仓库进行克隆,将远程仓库克隆到本地的命令形式为:

git clone 远程Git仓库地址

13 工作目录、暂存区以及版本库概念

版本库:git隐藏文件就是版本库,版本库存储了很多配置信息、日志信息和文件版本信息等

工作目录(工作区):包含git文件夹的目录就是工作目录,主要用于存放开发的代码

暂存区:git文件夹中有很多文件,其中一个index文件就是暂存区,也可以叫做stage。暂存区是一个临时保存修改文件的地方

14 Git工作目录下文件的两种状态

Git工作目录下的文件存在两种状态:

Unmodified 未修改状态

Modified 已修改状态

Staged 已暂存状态

这些文件的状态会随着我们执行Git的命令发生变化

15 本地仓库 *** 作

git status 查看文件状态

也可以使用git status -s使输出信息更简洁

git add 将未跟踪的文件加入暂存区,将已经修改的文件加入暂存区也是通过这个命令

git reset 将暂存区文件取消暂存

git commit -m “你的说明” 将暂存区文件提交到本地仓库

git rm 删除文件 说明:这种 *** 作是直接将文件加入到暂存区里面,直接提交到本地仓库生效,而直接删除的话没有进入到暂存区,需要先把文件加入到暂存区之后,再提交到本地仓库。

将文件添加至忽略列表

一般我们总会有些文件无需纳入Git的管理,也不希望他们总出现在未跟踪文件列表。通常这些都是自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。在这种情况下,我们可以在工作目录中创建一个名为gitnore的文件(文件名称固定),列出忽略的文件模式。下面是一个示例:#代表注释

由于windows无法创建不含文件名的文件,因此我们需要在bash窗口中用如下命令创建。

git log 查看日记记录

16 远程仓库 *** 作

如果想查看已经配置的远程仓库服务器,可以运行git remote 命令。它会列出指定的每一个远程服务器的简写。如果已经克隆了远程仓库,那么至少可以看见origin,这是Git克隆的仓库服务器的默认名字

git remote -v 可以查看对远程仓库详细一点的说明

git remote show origin 可以查看对origin更详细的远程仓库的说明

运行git remote add 添加一个远程Git仓库,同时指定一个可以引用的简写

如果你想获得一份已经存在了的Git仓库的拷贝,这时需要用到 git clone 命令。Git克隆的是Git仓库服务器上的几乎所有数据(包括日志信息、 历史 记录等),而不仅仅是复制工作所需要的文件。当你执行git clone 命令的时候,默认配置下Git仓库中的每一个文件的每一个版本都将被拉取下来。

如果因为一些原因想要移除一个远程仓库,可以使用git remote rm

注意:此命令只是从本地移除远程仓库的记录,并不会影响到远程仓库

git fetch 是从远程仓库获取最新版本到本地仓库,不会自动merge

说明:如果使用fetch命令,拉取的文件会放到版本库里面,不会自动整合到工作区,如果需要整合到工作区,需要使用 git merge 远程仓库别名/远程仓库分支

git pull 是从远程仓库获取最新版本并merge到本地仓库

注意:如果本地仓库不是从远程仓库克隆,而是本地创建的仓库,并且仓库中存在文件,此时再从远程仓库中拉取文件的时候会报错(fatal:refusing to merge unrelated histories),解决此我呢提可以在git pull 命令后加入参数 --allow-unrelated-histories

git push

17 Git分支

几乎所有的版本控制系统都是以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。Git的master是一个特殊分支。它跟其它分支没有区别。之所以每一个仓库都有mater分支,是因为git init默认创建它,并且大多数人都懒得去改动它。

# 列出所有本地分支

$ git branch

#列出所有远程分支

$ git branch -r

#列出所有本地分支和远程分支

$git branch -a

git branch 分支名称

git checkout 分支名称

git push 远程仓库别名 远程仓库分支

git merge 分支名称 说明:在当前分支下合并其他分支

注意:如果两个分支存在同样的文件名且同行的内容不一样,那么会产生矛盾,需要自己手动修改产生矛盾后的文件,然后添加到暂存区然后提交。

git branch -d 分支名称

如果要删除的分支中进行了一些开发动作,此时执行上面的删除命令并不会删除分支,可以将命令中的-d参数改为-D

如果要删除远程仓库中的分支,可以使用命令git push origin -d branchName

18 Git标签

像其他版本控制系统一样,Git可以给 历史 中的某一给提交打上标签,以示重要。比较有代表性的是人们会使用这个功能来标记发布结点(v10、v12等)。标签指的是某个分支某个特定时间点的状态。通过标签,可以很方便地切换到标记时的状态。

#新建一个tag

$ git tag [tagName]

$ git tag

#新建一个分支,指向某个tag

$ git checkout -b [branch] [tag]

#删除本地tag

$git tag -d[tag]

#删除远程tag

$git push origin :refs/tags/[tag]

Git 是一个很强大的分布式版本管理工具,它不但适用于管理大型开源软件的源代码(如:linux kernel),管理私人的文档和源代码也有很多优势(如:wsi-lgame-pro)
Git 的更多介绍,请参考我的上一篇博客:Git 版本管理工具
一、 Git 命令初识
在正式介绍Git命令之前,先介绍一下Git 的基本命令和 *** 作,对Git命令有一个总体的认识
示例:从Git 版本库的初始化,通常有两种方式:
1)git clone:这是一种较为简单的初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份
例如:git  clone  git://githubcom/someone/some_projectgit   some_project 
上面的命令就是将'git://githubcom/someone/some_projectgit'这个URL地址的远程版本库,完全克隆到本地some_project目录下
2)git init 和 git remote:这种方式稍微复杂一些,当你本地创建了一个工作目录,你可以进入这个目录,使用'git init'命令进行初始化;Git以后就会对该目录下的文件进行版本控制,这时候如果你需要将它放到远程服务器上,可以在远程服务器上创建一个目录,并把可访问的URL记录下来,此时你就可以利用'git remote add'命令来增加一个远程服务器端,
例如:git  remote  add  origin  git://githubcom/someone/another_projectgit
上面的命令就会增加URL地址为'git: //githubcom/someone/another_projectgit',名称为origin的远程服务器,以后提交代码的时候只需要使用 origin别名即可
二、 Git 常用命令
1) 远程仓库相关命令
检出仓库:        $ git clone git://githubcom/jQuery/jquerygit
查看远程仓库:$ git remote -v
添加远程仓库:$ git remote add [name] [url]
删除远程仓库:$ git remote rm [name]
修改远程仓库:$ git remote set-url --push [name] [newUrl]
拉取远程仓库:$ git pull [remoteName] [localBranchName]
推送远程仓库:$ git push [remoteName] [localBranchName]
如果想把本地的某个分支test提交到远程仓库,并作为远程仓库的master分支,或者作为另外一个名叫test的分支,如下:
$git push origin test:master         // 提交本地test分支作为远程的master分支
$git push origin test:test              // 提交本地test分支作为远程的test分支
2)分支(branch) *** 作相关命令
查看本地分支:$ git branch
查看远程分支:$ git branch -r
创建本地分支:$ git branch [name] ----注意新分支创建后不会自动切换为当前分支
切换分支:$ git checkout [name]
创建新分支并立即切换到新分支:$ git checkout -b [name]
删除分支:$ git branch -d [name] ---- -d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D选项
合并分支:$ git merge [name] ----将名称为[name]的分支与当前分支合并
创建远程分支(本地分支push到远程):$ git push origin [name]
删除远程分支:$ git push origin :heads/[name] 或 $ gitpush origin :[name] 
创建空的分支:(执行命令之前记得先提交你当前分支的修改,否则会被强制删干净没得后悔)
$git symbolic-ref HEAD refs/heads/[name]
$rm git/index
$git clean -fdx
3)版本(tag) *** 作相关命令
查看版本:$ git tag
创建版本:$ git tag [name]
删除版本:$ git tag -d [name]
查看远程版本:$ git tag -r
创建远程版本(本地版本push到远程):$ git push origin [name]
删除远程版本:$ git push origin :refs/tags/[name]
合并远程仓库的tag到本地:$ git pull origin --tags
上传本地tag到远程仓库:$ git push origin --tags
创建带注释的tag:$ git tag -a [name] -m 'yourMessage'
4) 子模块(submodule)相关 *** 作命令
添加子模块:$ git submodule add [url] [path]
如:$git submodule add git://githubcom/soberh/ui-libsgit src/main/webapp/ui-libs
初始化子模块:$ git submodule init  ----只在首次检出仓库时运行一次就行
更新子模块:$ git submodule update ----每次更新或切换分支后都需要运行一下
删除子模块:(分4步走哦)
1) $ git rm --cached [path]
2) 编辑“gitmodules”文件,将子模块的相关配置节点删除掉
3) 编辑“ git/config”文件,将子模块的相关配置节点删除掉
4) 手动删除子模块残留的目录
5)忽略一些文件、文件夹不提交
在仓库根目录下创建名称为“gitignore”的文件,写入不需要的文件夹名或文件,每个元素占一行即可,如
target
bin
db
三、 Git 命令详解
现在我们有了本地和远程的版本库,让我们来试着用用Git的基本命令:
git pull:从其他的版本库(既可以是远程的也可以是本地的)将代码更新到本地,例如:'git pull origin master'就是将origin这个版本库的代码更新到本地的master主枝,该功能类似于SVN的update
git add:是将当前更改或者新增的文件加入到Git的索引中,加入到Git的索引中就表示记入了版本历史中,这也是提交之前所需要执行的一步,例如'git add app/model/userrb'就会增加app/model/userrb文件到Git的索引中,该功能类似于SVN的add
git rm:从当前的工作空间中和索引中删除文件,例如'git rm app/model/userrb',该功能类似于SVN的rm、del
git commit:提交当前工作空间的修改内容,类似于SVN的commit命令,例如'git commit -m story #3, add user model',提交的时候必须用-m来输入一条提交信息,该功能类似于SVN的commit
git push:将本地commit的代码更新到远程版本库中,例如'git push origin'就会将本地的代码更新到名为orgin的远程版本库中
git log:查看历史日志,该功能类似于SVN的log
git revert:还原一个版本的修改,必须提供一个具体的Git版本号,例如'git revert bbaf6fb5060b4875b18ff9ff637ce118256d6f20',Git的版本号都是生成的一个哈希值
 
上面的命令几乎都是每个版本控制工具所公有的,下面就开始尝试一下Git独有的一些命令:
git branch:对分支的增、删、查等 *** 作,例如'git branch new_branch'会从当前的工作版本创建一个叫做new_branch的新分支,'git branch -D new_branch'就会强制删除叫做new_branch的分支,'git branch'就会列出本地所有的分支
git checkout:Git的checkout有两个作用,其一是在不同的branch之间进行切换,例如'git checkout new_branch'就会切换到new_branch的分支上去;另一个功能是还原代码的作用,例如'git checkout app/model/userrb'就会将userrb文件从上一个已提交的版本中更新回来,未提交的内容全部会回滚
git rebase:用下面两幅图解释会比较清楚一些,rebase命令执行后,实际上是将分支点从C移到了G,这样分支也就具有了从C到G的功能
 
 
git reset:将当前的工作目录完全回滚到指定的版本号,假设如下图,我们有A-G五次提交的版本,其中C的版本号是 bbaf6fb5060b4875b18ff9ff637ce118256d6f20,我们执行了'git reset bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那么结果就只剩下了A-C三个提交的版本
 
git stash:将当前未提交的工作存入Git工作栈中,时机成熟的时候再应用回来,这里暂时提一下这个命令的用法,后面在技巧篇会重点讲解
git config:利用这个命令可以新增、更改Git的各种设置,例如'git config branchmasterremote origin'就将master的远程版本库设置为别名叫做origin版本库,后面在技巧篇会利用这个命令个性化设置你的Git,为你打造独一无二的 Git
git tag:可以将某个具体的版本打上一个标签,这样你就不需要记忆复杂的版本号哈希值了,例如你可以使用'git tag revert_version bbaf6fb5060b4875b18ff9ff637ce118256d6f20'来标记这个被你还原的版本,那么以后你想查看该版本时,就可以使用 revert_version标签名,而不是哈希值了
Git 之所以能够提供方便的本地分支等特性,是与它的文件存储机制有关的。Git存储版本控制信息时使用它自己定义的一套文件系统存储机制,在代码根目录下有一个git文件夹,会有如下这样的目录结构:
 
 
有几个比较重要的文件和目录需要解释一下:HEAD文件存放根节点的信息,其实目录结构就表示一个树型结构,Git采用这种树形结构来存储版本信息,那么HEAD就表示根;refs目录存储了你在当前版本控制目录下的各种不同引用(引用指的是你本地和远程所用到的各个树分支的信息),它有heads、remotes、stash、tags四个子目录,分别存储对不同的根、远程版本库、Git栈和标签的四种引用,你可以通过命令'git show-ref'更清晰地查看引用信息;logs目录根据不同的引用存储了日志信息。因此,Git只需要代码根目录下的这一个git目录就可以记录完整的版本控制信息,而不是像SVN那样根目录和子目录下都有svn目录。那么下面就来看一下Git与SVN的区别吧
 
四、 Git 与SVN 比较
SVN(Subversion)是当前使用最多的版本控制工具。与它相比较,Git 最大的优势在于两点:易于本地增加分支和分布式的特性。
下面两幅图可以形象的展示Git与SVN的不同之处:
 
------------
 
1)本地增加分支
图中Git本地和服务器端结构都很灵活,所有版本都存储在一个目录中,你只需要进行分支的切换即可达到在某个分支工作的效果
而SVN则完全不同,如果你需要在本地试验一些自己的代码,只能本地维护多个不同的拷贝,每个拷贝对应一个SVN服务器地址
举一个实际的例子:
使用SVN作为版本控制工具,当正在试图增强一个模块,工作做到一半,由于会改变原模块的行为导致代码服务器上许多测试的失败,所以并没有提交代码。
这时候假如现在有一个很紧急的Bug需要处理, 必须在两个小时内完成。我只好将本地的所有修改diff,并输出成为一个patch文件,然后回滚有关当前任务的所有代码,再开始修改Bug的任务,等到修改好后,在将patch应用回来。前前后后要完成多个繁琐的步骤,这还不计中间代码发生冲突所要进行的工作量。
可是如果使用Git, 我们只需要开一个分支或者转回到主分支上,就可以随时开始Bug修改的任务,完成之后,只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意,每一个新的任务都可以开一个分支,完成后,再将它合并到主分支上,轻松而优雅。
2)分布式提交
Git 可以本地提交代码,所以在上面的图中,Git有利于将一个大任务分解,进行本地的多次提交
而SVN只能在本地进行大量的一次性更改,导致将来合并到主干上造成巨大的风险
3)日志查看
Git 的代码日志是在本地的,可以随时查看
SVN的日志在服务器上的,每次查看日志需要先从服务器上下载下来
例如:代码服务器在美国,当每次查看几年前所做的工作时,日志下载可能需要十分钟,这不能不说是一个痛苦。但是如果迁移到Git上,利用Git日志在本地的特性,查看某个具体任务的所有代码历史,每次只需要几秒钟,大大方便了工作,提高了效率。
当然分布式并不是说用了Git就不需要一个代码中心服务器,如果你工作在一个团队里,还是需要一个服务器来保存所有的代码的。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/13014328.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-29
下一篇 2023-05-29

发表评论

登录后才能评论

评论列表(0条)

保存