如果把互联网上的纷繁代码比作一片海洋,那么git就是在这片海洋上航行的船只,正所谓“水可载舟,亦可覆舟”,git使用恰当可以远征星辰,不然可能会坠入无穷无尽的代码海洋无法自拔。书回正传,我们的征途是星辰大海!

扬帆起航

git的下载安装暂且不表,可参考网站https://git-scm.com/downloads

git的安装只是个入门条件,下面如何使用git命令控制代码才是远征的基础。那么从何开始呢?让我们一步步说起。

要想扬帆起航,首先得有艘帆船吧。我们要在本地建立一个项目,之后将本地项目初始化为git仓库,可以使用

git init [--bare]

初始化本地项目,执行后会在当前执行目录下生成.git文件夹,这也就是我们的帆船了。[--bare]可选参数,可初始化裸仓库,裸仓库可以与源码项目分离,此时在当前目录下不会生成.git文件夹,而是直接生成.git文件夹下的包括hooks、info、objects、refs共四个文件夹和config、description、HEAD三个文件。

在初始化裸仓库后若想关联源码,只需进入hooks目录新建post-receive.sample文件,并添加如下内容:

git --work-tree=<project-dir> --git-dir=<local-url> checkout -f

其中<project-dir>为本地项目文件路径,<local-url>为本地git仓库路径。

对于当前目录下的.git文件夹所代表的本地仓库,不同的帆船有不同的配置,我们使用

git config –list

显示当前git配置。如果内容过多可以使用上下键翻页,查看结束按q退出即可。同时使用

git config –e [--global]

以vim形式编辑修改git配置文件。

git config [--global] user.name “name”

形式修改指定配置,其中[--global]可选,为全局配置,name为用户名配置。

git仪表盘

图 1 Git指令关系图

建立git仓库作为帆船后,就可以在当前目录下任意使用git指令遨游了。我们需要先认识下git控制的命令仪表盘。

如图1所示,git整艘船主要分为四大区域,包括Remote远程仓库,Repository本地仓库,Index/Stage暂存区,Workspace工作区,不同区域之间可以使用相关指令进行代码操作。在上节使用git init创建的文件夹下,会生成名为.git的隐藏文件夹,四大区域的配置都储存在该文件夹下。其中在远程仓库和本地仓库中,储存有不同的branch分支,工作区和暂存区的文件只能针对某一分支进行修改提交操作,当然也可以使用分支操作指令对不同的分支进行增删合并等操作。

针对一些仓库的操作指令,使用前请务必保持头脑清醒,不然你的一个蝴蝶煽动翅膀似的操作,可能会引发仓库里的一场代码风暴,造成不可挽回的结果。

根据不同命令操作区域,可以将git命令大致分为全局显示信息、工作区与远程仓库交互、工作区与本地仓库交互、工作区与暂存区交互、暂存区与本地仓库交互、本地仓库与远程仓库交互、以及仓库内部分支操作。下面对这些命令进行了粗略的统计介绍,详细使用方式可参考git官方文档介绍,如有不足还请补充。

显示信息

git help [command]

获取命令的帮助信息。

git status

显示所有变更文件

git log [--stat] [--graph]

显示当前分支的版本信息。[--stat]参数指定显示commit发生变更的文件。[--graph]参数以数据图形式查看合并分支记录。

git blame <file>

显示文件的每一行最后修改的版本和作者

git show [commit][:filename]

显示某次提交的变更内容。其中[commit]为某次提交版本,也可在:后边加参数[filename]指定查看某个文件内容。

git diff [HEAD] [first-branch] [second-branch]

显示文件差异。无参时比较缓存区和上一次commit的差异;[HEAD]为工作区与当前分支最新commit的差异;或者两个分支之间的差异。

git reflog

显示已执行过的所有git动作日志。

工作区与远程仓库

git pull <remote> <branch>

拉取远程仓库的变化,并与本地分支合并。<remote>为远程仓库名,<branch>为远程仓库中的某一分支名。

工作区与本地仓库

git checkout [–b] <branch> [tag]

将暂存区切换到分支名。其中[-b]参数可选,当分支不存在时则创建,<branch >必须,为本地仓库分支,[tag]可选,指定切换到仓库分支中的某条标签,不标注则默认为切换分支的最近一次提交。

工作区与暂存区

git add <dir>

添加指定目录到暂存区,<dir>为添加路径,允许多个,包括子目录都会添加到暂存区中等待提交。

git rm [--cached] <file>

删除暂存区中的文件,<file>为暂存区中要删除的文件全路径,[--cache]可选参数,只会停止继续追踪指定文件,但该文件目前仍然保留在暂存区。

git mv <file-old> <file-new>

修改暂存区中的文件名,<file-old>为原文件全路径,<file-new>为修改后的文件全路径。

git tag

查看暂存区中的所有标签信息。

git tag –a <tag> [commit]

新建一个标签。[tag]为标签名;[commit]为指定的一次从暂存区到本地仓库的提交中,默认为最新一次提交。

git tag –d [tag]

删除本地标签。

暂存区与本地仓库

git commit [--amend] [–m <message>] [file] [-a] [-v]

从暂存区提交到本地仓库。其中[--amend]重做上次从本地项目到暂存区的commit,当代码与上次提交相比无变化时使用,只修改上次commit的<message>内容;[-m]参数为提交信息,<message>必写且详写,以区别提交代码的修改内容;[file]为指定暂存区中的文件;[-a]可直接提交项目中的变化到本地仓库,在没有新增文件时不需每次先git add提交到暂存区再提交到本地仓库;[-v]可以在提交时显示所有变化文件的diff信息。

git cherry-pick [commit]

选择一个commit版本合并到当前分支,[commit]为暂存区中的commit版本。

本地仓库与远程仓库

git remote [-v]

查看关联的远程仓库信息。[-v]可以查看详细信息。

git remote add <remote-name> <remote-url>

本地路径关联远程仓库。

<remote-name>必要参数,为远程仓库的名字,默认是origin。

<remote-url>必要参数,为远程仓库的地址,git服务器通常都是以.git结尾。

git remote remove <remote-name>

删除关联的远程仓库。其中<remote-name>为远程仓库的名字。

git push [remote] [branch] [--force]

推送本地指定分支到远程仓库。[remote]为远程仓库名,[branch]为本地分支名,[--force]为强制推送本地到远程,如有冲突则覆盖。

git fetch <remote>

将远程仓库拉到本地仓库。<remote>为远程仓库名。

git clone <url> [name]

创建一个本地仓库。<url>必须,可以是远程git服务器上的仓库,也可以是本地仓库。[name]选填是创建的新仓库名,默认与原仓库名一致。

分支指令

git branch [-r] [-a]

查看分支信息,无参只会查看本地仓库所有分支,[-r]是远程仓库所有分支,[-a]则是包括本地和远程仓库所有的所有分支。

git branch [branch-name] [commit]

在本地仓库新建分支,但暂存区仍然指向当前分支。其中[branch-name]为新建的本地仓库分支;[commit]可将分支指向指定commit版本。

git branch –track [local-branch-name] [remote-branch]

新建一个分支,并连接指定的远程分支。其中[local-branch-name]为本地仓库新建分支,[remote-branch]为远程仓库分支。

git branch –set-upstream [local-branch] [remote-branch]

连接本地仓库分支与远程仓库分支,其中[local-branch]为本地仓库已有分支,[remote-branch]为远程仓库分支。

git branch –d [branch]

删除本地仓库分支,[branch]为本地仓库中的已有分支。

git branch -m [branch-old] [branch-new]

修改本地仓库分支,其中[branch-old]为原分支,[branch-new]为改名后的分支。

git branch –dr [remote-branch]

删除远程仓库分支,[remote-branch]为远程仓库中的分支。不推荐使用,如果远程仓库未更新,可能会执行失败,推荐使用git push origin-delete [remote-branch]。

git merge <local-branch>

合并指定分支到当前分支,<local-branch>为本地仓库中的已有分支。

git rebase <remote-branch>

将当前分支的提交复制到指定的远程分支上,<remote-branch>为指定远程仓库中的已有分支。

git reset [--mixed|--soft|--hard] [commit]

重置仓库索引,重置一旦清空后的内容不会在仓库历史版本中留下历史记录。[--mixed]为默认参数,重置后只在工作区保留原节点修改文件,清空暂存区和本地仓库并均恢复到指定重置节点;[--soft]为软重置,重置后在工作区和暂存区均保留原节点修改文件,清空本地仓库并恢复到指定重置节点;[--hard]为硬重置,重置后均不会保留原节点修改文件。[commit]为要重置的节点号。

git revert [commit]

还原文件到之前修改提交节点时,会在仓库历史版本中留下历史记录。[commit]为要还原的节点号。

常规操作

git这艘大船虽然功能繁杂,但是用起来是有章可循的。入门之后就驾驶下这艘大船来试试吧。

一般git有三种工作流程,包括Git flow,项目存在两个长期分支(主分支master和开发分支develop),适用于基于版本发布的普通项目;Github flow,只有一个长期分支(主分支master),适用于持续发布的小型项目;Gitlab flow,项目存在多个长期分支,其中主分支master是其他所有分支的上游,只有上游分支采纳的代码才能应用到其下游分支,适用于长期维护的大型项目。

图2展示了一次项目git流程演变过程,在master主分支上有Tag1-Tag4四次代码更新,其中基于Tag2对应的版本1号创建了新的branch1分支,新分支创建后自动生成了版本2号并打上了Tag2-1标签,之后master主分支和branch1分支都同时进行了代码演变,在branch1分支提交的版本4号及标签Tag2-3之后,branch1分支合并到了master主分支,合并前master主分支位于版本5号,合并后可能重新生成版本6号,并打上新的tag4标签,之后master主分支修改提交为版本7号,而branch1分支则停留在tag2-3标签的位置处。

图 2 Git流程示意图

在这份项目流程中,分支创建之后,可能在不同的阶段修改提交文件,根据对文档的读取权限范围,我们可以形象地将这些阶段划分为三种身份类型,船长、水手和游客。船长身份,作为项目管理者,主要负责远程仓库和本地仓库之间的分支操作,协调分支冲突;水手身份,作为项目贡献者,主要负责某一分支的迭代更新;游客身份,作为项目使用者,只是访问使用仓库及其分支内容,不能提交任何修改。同一人在项目的不同阶段可以是其中任意一种身份,下面以这三种身份为维度简单介绍下使用到的相关git指令步骤,并辅以示意图方式直观解释git指令执行前后git项目变化。

项目使用者-游客

作为git项目的游客,当然只能将项目从远程仓库拉取到本地使用,期间除了切换仓库分支外不会涉及其他远程操作。

git pull origin master

拉取远程仓库origin的master分支到本地。

git checkout branch1 tag1

切换到分支branch1。

项目贡献者-水手

作为项目的水手,除了可以使用游客的功能指令外,还会涉及到修改工作区文件,并将工作区文件提交到暂存区和仓库等任务。通常水手只需要维护仓库中的某一条分支并只对该分支负责,因此水手更注重工作区的代码文件修改工作。

git pull origin dev:branch1

拉取远程仓库origin的dev分支到本地,并与本地branch1分支合并。工作区中文件即显示branch1分支,可在工作区做文件修改操作。

git add .

在工作区的文件修改之后,可先添加当前目录所有文件到暂存区,之后可继续修改工作区其他文件,也可将暂存区文件提交到本地仓库。

git rm –cached file

针对工作区编译生成的配置file文件,一般不需提交到仓库,可使用该命令将file文件从暂存区删除并停止后续追踪。另外一种添加忽略文件的方式,在.git文件夹的同级目录下新建.gitignore文件,在该文件中根据规则增加要忽略的文件路径,之后将该文件提交到本地仓库中。

git commit –m “commit message 1”

在确保工作区的所有修改文件均已提交到暂存区后,便将暂存区的修改提交到本地仓库,同时附带当次提交信息。每次提交都会在本地仓库生成一个新的提交commit版本号,由于提交的commit版本号是冗长的sha1码,所以为了方便后期溯源,通常会在主要的commit号版本上再打一个鲜明的标签以作标记。

git tag tag1 1

在提交的commit版本号为1的节点上打标签,打上标签后的commit号便可使用简短的标签名tag1访问,以便后期对该节点溯源。

git push origin branch1:dev –tags

将本地branch1分支及相关标签推送到远程仓库origin的dev分支。如果本地branch1分支已经与远程dev分支建立追踪关系,也可直接使用

git push origin branch1 --tags

指令。

git branch –set-upstream-to=origin/dev
branch1

设置本地仓库的branch1分支与远程仓库origin的dev分支的追踪关系。通常从远程分支pull到本地的分支都已经建立了追踪关系,不需要手动修改。

git branch –vv

查看本地分支及追踪的远程分支信息。

项目管理者-船长

作为项目的船长,自然拥有整个git这艘大船的项目所有权限,除了使用水手的操作指令外,另需完成分支增删合并等任务。通常船长是项目仓库的创建者,负责管理维护仓库的各分支关系,对项目的整个仓库负责,因此相较于水手,船长更注重仓库的分支管理相关工作。

git clone https://github.com/xxx.git -b dev

克隆远程仓库的dev分支到本地,默认会将文件更新到本地仓库建立的同名dev分支。

git checkout –b branch1 origin/dev

在本地仓库新建branch1分支,与远程仓库origin中的dev分支对应,并在本地切换到branch1分支。如果不指定远程仓库及分支信息origin/dev,则默认从本地仓库dev分支创建。至此可以切换为水手身份,从该分支更新代码,并将修改文件提交到该branch1分支。

git add .

git commit –m “modify file commit”

在完成对工作区文件的修改之后,使用水手身份将工作区的修改提交到本地branch1分支。

git checkout dev

切换到本地仓库的dev主分支,作为本地仓库与远程仓库代码合并的操作分支。

git fetch origin dev

拉取远程仓库origin中的dev分支到本地仓库当前dev分支

git pull

将本地仓库dev分支的文件修改合并到工作区。

git merge branch1

将本地仓库的branch1分支合并到当前dev分支。如果当前dev分支与branch1分支有冲突,需要根据冲突文件提示分别修改,之后再重新合并该分支。

git checkout branch1 build/files

或者只将branch1分支的build/files目录下所有文件合并到本地仓库的当前dev分支。同样需要做冲突处理。

git push origin dev:dev –tags

向远程仓库origin中的dev分支并推送本地仓库dev分支。推送时如果确认以本地分支覆盖远程分支,则可使用

git push —force origin dev:dev –tags

强制推送。最后如果想删除远程分支,有以下两条指令

git push origin –delete dev

git push origin :dev

这两种方式都可以删除指定的远程仓库origin中的dev分支。

应急预案

上面的图2Git流程图简单涉及了一次版本演变过程中的一些git信息,包括分支切换,打标签等,看上去简单易懂,而实际我们工作中驾船航行时却并不总是风平浪静。

通常出现的紧急情况需要修改分支版本,包括变基、还原、重置等操作,针对不同场景需要选择不同的操作方式。

变基

git rebase master

变基会将当前分支的修改文件复制到master分支,同时创建新的commit版本号并修改项目的历史记录。当master分支已经更新,且确认当前分支与master分支没有冲突,那可以使用变基以便当前分支获取master分支的更新。

重置

git reset 1

将HEAD重置到历史提交版本1的状态,还原仓库和暂存区的文件与提交版本1一致,工作区维持修改文件状态。

还原

git revert 1

重新创建一次提交版本节点,文件状态与历史提交版本1一致,工作区、暂存区与仓库均保持一致。提交版本2相对于提交版本1新增了file.txt文件,执行该指令后,在提交版本3中将恢复到提交版本1的状态,因此提交版本3相对于提交版本2则删除了file.txt文件。

强制远程覆盖本地

git fetch –all

拉取远程所有仓库到本地仓库,工作区不会有任何合并更新。

git reset –hard origin/dev

把工作区HEAD指向最新的远程仓库origin中的dev版本。

待补充

除此之外在驾驭git这艘大船时肯定还会出现各种意外,届时将酌情补充。

 SHAPE  \* MERGEFORMAT

Remote

Repository

fetch/clone

pull

add

Index/Stage

Workspace

commit

checkout

push

使用git畅游代码的海洋的更多相关文章

  1. 如何在 Visual Studio 中使用 Git 同步代码到 CodePlex

    开源社区不管在国内还是国外都很火热,微软也曾因为没有开源而倍受指责,但是随着 .Net framework.ASP.Net MVC等框架的逐渐开源,也让大家看到了微软开源的步伐.CodePlex 则是 ...

  2. git commit 代码时提示: Warning: Your console font probably doesn‘t support Unicode.

    git 提交代码是会遇到以下问题, git commit 代码时提示: Warning: Your console font probably doesn‘t support Unicode. If ...

  3. 如何清洗 Git Repo 代码仓库

    git prune 如何清洗 Git Repo 代码仓库       在腾讯云上创建您的SQL Cluster>>> »   相信不少团队的代码仓库 Git Repo 变得越来越大. ...

  4. 软工实践练习一——使用Git进行代码管理心得

    在github.com的操作 注册 创建Organization 将指定代码库fork到小组Organization下 在Organization下创建repository 这些操作在学校的机房已经完 ...

  5. 软工实践练习——使用Git进行代码管理

    GITHUB上的预备活动: 注册 创建小组Organization,邀请组员进来 将代码库fork到小组Organization底下 下载并使用GIT: Git的安装 使用Git进行代码管理 1.从百 ...

  6. 软工实践练习——使用git进行代码管理心得

    一.在Github上注册账户.其中创建organization在小组成员的账户上创建,并在其账户上创建了小组的版本库.在创建organization的过程中,参考了助教提供的博客:http://sef ...

  7. [转]如何在 Visual Studio 中使用 Git 同步代码到 CodePlex

    本文转自:http://www.cnblogs.com/stg609/p/3673782.html 开源社区不管在国内还是国外都很火热,微软也曾因为没有开源而倍受指责,但是随着 .Net framew ...

  8. 用开源中国(oschina)Git管理代码(整合IntelliJ 13.1.5)

    简介 开源中国提供了Git服务(地址:http://git.oschina.net/),在速度上比国外的github要快很多.使用了一段时间,感觉很不错.oschina git提供了演示平台,可以运行 ...

  9. 支持Git的代码托管网站

    支持Git的代码托管网站: https://github.com/https://code.google.com http://www.codeplex.com/ http://git.oschina ...

随机推荐

  1. CSS 超出行显示...

    一行超出 overflow:hidden; white-space:nowrap; text-overflow:ellipsis; 多行超出 overflow: hidden; text-overfl ...

  2. 啪啪,打脸了!领导说:try-catch必须放在循环体外!

    哈喽,亲爱的小伙伴们,技术学磊哥,进步没得说!欢迎来到新一期的性能解读系列,我是磊哥. 今天给大家带来的是关于 try-catch 应该放在循环体外,还是放在循环体内的文章,我们将从性能和业务场景分析 ...

  3. jchdl - RTL实例 - And2And(结构体嵌套的使用)

    https://mp.weixin.qq.com/s/PQIPkDymvcGc_re8ux50vA   结构体可以嵌套使用.   参考链接 https://github.com/wjcdx/jchdl ...

  4. JSON.parse() 的实现

    目录 1. JSON.parse() 2. 前置知识 2.1 JSON格式中的数据类型 2.2 转义字符的处理 2.2 判断对象是否相等 2.3 寻找匹配的字符串 2.4 基础的递归思想 3. 实现流 ...

  5. 百度云百度网盘VIP不限速破解版绿色版-实测可用

    百度云百度网盘不限速VIP破解版绿色版-下载地址:https://www.90pan.com/b1548999

  6. 我终于搞清了啥是 HTTPS 了

    引言 最近上海连续下了一周雨,温度一夜之间回到解放前,穿夏装的我被冻得瑟瑟发抖,躲在家里哪也不想去. 在家百无聊赖的刷着网页,看到公众号后台的留言,有同学问我 HTTP 和 HTTPS 有啥区别? 这 ...

  7. Java实现 LeetCode 352 将数据流变为多个不相交区间

    352. 将数据流变为多个不相交区间 给定一个非负整数的数据流输入 a1,a2,-,an,-,将到目前为止看到的数字总结为不相交的区间列表. 例如,假设数据流中的整数为 1,3,7,2,6,-,每次的 ...

  8. Java实现 LeetCode 343 整数拆分(动态规划入门经典)

    343. 整数拆分 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × ...

  9. Java实现 LeetCode 284 顶端迭代器

    284. 顶端迭代器 给定一个迭代器类的接口,接口包含两个方法: next() 和 hasNext().设计并实现一个支持 peek() 操作的顶端迭代器 – 其本质就是把原本应由 next() 方法 ...

  10. Java实现 LeetCode 152 乘积最大子序列

    152. 乘积最大子序列 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] ...