如果把互联网上的纷繁代码比作一片海洋,那么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. 8.Hash集合类型操作使用

    数据类型Hash (1)介绍 hash数据类型存储的数据与mysql数据库中存储的一条记录极为相似 Redis本身就类似于Hash的存储结构,分为key-value键值对,实际上它的Hash数据就好像 ...

  2. 3.Linux如何管理分区

    上一次谈完了硬盘与分区的基础知识,下面谈一下Linux如何管理分区. Linux管理硬件和windows完全不同.任何东西(包括硬件)在Linux看来都是文件设备,有字符和二进制形式的设备.如打印机. ...

  3. Linux服务器程序--大数据量高并发系统设计

         在Linux服务器程序中,让系统能够提供以更少的资源提供更多的并发和响应效率决定了程序设计价值!怎样去实现这个目标,它其实是这么多年以来一直追逐的东西.最开始写代码时候,省去一个条件语句.用 ...

  4. @Spring Boot程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码

    前言 这篇其实是对一年前的一篇文章的补坑. @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码 当时,就是在spring mvc应用里定义一个 ...

  5. 集合概述及Collection接口的常用方法

    java集合像是一种容器,可以动态的把多个对象的引用放到容器中 java的集合类可以用于存储数量不等的多个对象,还可以用于保存具有映射关系的关联数组 package com.aff.coll; imp ...

  6. 第一次写js轮播图

    仿小米首页轮播图(注意事项) 布局部分 1.用ul包裹li再包裹a的形式来装图片,建立focus类: <div class="focus"> <ul> &l ...

  7. 容器技术之Dockerfile (一)

    在前边的随笔中我们聊到了docker的基本命令,镜像,网络,存储卷以及基于现有容器制做docker镜像,相关随笔可参考https://www.cnblogs.com/qiuhom-1874/categ ...

  8. 报错:The server cannot be started because one or more of the ports are invalid. Open the server editor and correct the invalid ports.

    今天重装eclipse和Tomcat,启动时候报标题错“The server cannot be started because one or more of the ports are invali ...

  9. jchdl - GSL Node

    https://mp.weixin.qq.com/s/Oa4qgjIUccu5Y-Jlqcyn_A   org.jchdl.model.gsl.core.meta.Node.java   ​​ gen ...

  10. Java实现 LeetCode 376 摆动序列

    376. 摆动序列 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5 ...