新建日志   展示   相册  日志列表
 

git repo工具详细使用教程 .repos文件怎麽用


源码是通过 repo 工具进行管理的,因此我们需要执行特定的命令来检出(即同步或下载)源码。运行以下命令进行检出:


.repo/repo/repo sync -l
python3 .repo/repo/repo sync -l

注意:上述提供的两个命令中,您只需选择其一执行。如果在运行“.repo/repo/repo sync” ”到 命令时遇到 Python 相关的错误,这通常是由于 Python 版本不兼容所导致的。为了解决这个问
用 题,您可以在运行该命令之前,明确指定使用 Python3 版本来执行换 ,如果不行请切换 Python3的不同版本( 推荐 python3.8)。 是 还有一个错误就是 repo 的版本问题。

image

 当我们的默认 python 版本指向 python2.x 版本就会出现,上图 的错误,我们只需要使用 python3 版本进行检出。

image

 图 1.2.2 repo 版本问题

如果出现图 1.2.2 问题,可以运行以下命令进行解决:

cd .repo/repo/
git pull
cd ../../
.repo/repo/repo sync -l

image

 

image

 


git repo工具详细使用教程

git repo工具详细使用教程

转载: git repo工具详细使用教程

repo是什么?

repo是Google开发的用于管理Android版本库的一个工具,repo是使用Python对git进行了一定的封装,并不是用于取代git,它简化了对多个Git版本库的管理。用repo管理的版本库都需要使用git命令来进行操作。因此,使用repo工具之前,请先确保已经安装git。

为什么要用repo?

项目模块化/组件化之后各模块也作为独立的 Git 仓库从主项目里剥离了出去,各模块各自管理自己的版本。Android源码引用了很多开源项目,每一个子项目都是一个Git仓库,每个Git仓库都有很多分支版本,为了方便统一管理各个子项目的Git仓库,需要一个上层工具批量进行处理,因此repo诞生。
repo也会建立一个Git仓库,用来记录当前Android版本下各个子项目的Git仓库分别处于哪一个分支,这个仓库通常叫做:manifest仓库(清单库)。

repo下载安装

下载地址:https://mirrors.tuna.tsinghua.edu.cn/git/git-repo ,将下载下来的文件命名为repo,放在PATH环境变量所包含的目录下面,例如可以放在/usr/local/bin目录下(后面介绍均以放在/usr/local/bin目录下为例)。

或者,直接使用curl命令下载:

curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > /usr/local/bin/repo
bash

最后,修改repo文件的执行权限:chmod 777 /usr/local/bin/repo

其实下载下来的repo文件只是一个使用Python编写的引导脚本(Google 称之为 Repo launcher,本质上是一个python脚本,可以使用vim打开的),完整的repo(即,repo的主体部分)还没有下载。

repo help

查看repo帮助说明,该帮助列举了repo所支持的子命令,及各个子命令的简要介绍。
如果需要查看某个具体子命令的详细介绍,执行命令repo help <command>即可。例如查看repo init的帮助,可以输入repo help init

上一小节已经提及到了,下载下来的repo只是一个引导脚本,完整的repo工具还没有下载,如下图所示,此时使用repo help只能看到inithelp两个子命令,而且帮助信息中还会提示repo还未安装,需要执行repo init安装。(需要注意repo init需要跟参数的,后面会单独介绍repo init的使用)

在这里插入图片描述

当执行完repo init下载了完整的repo工具之后,再执行repo help就会看到repo更多的子命令。如下图所示:

在这里插入图片描述

repo version

命令格式:

repo version
bash

查看repo的版本

repo selfupdate

命令格式:

repo selfupdate
bash

用于 repo 自身的更新。如果有新版本的repo存在, 这个命令会升级repo到最新版本。通常这个动作在repo sync时会自动去做, 所以不需要最终用户手动去执行。

常用选项:

  • --no-repo-verify:不要验证repo源码.

repo init

repo init命令

命令格式:

repo init [options] [manifest url]
bash

例如:

repo init -u manifest_git_path -m manifest_file_name -b branch_name --repo-url=repo_url --no-repo-verify
bash

命令效果:
首先当前目录产生一个.repo目录
然后克隆一份repo的源代码到.repo/repo下,里面存放了其他repo子命令,即repo的主体部分。
接着从manifest_git_path仓库地址clone清单库到.repo/manifests.repo/manifests.git目录。
同时.repo目录下还包括manifest仓库(清单库)内容

常用选项:

  • -u:指定Manifest库的Git访问路径。唯一必不可少的选项
  • -m:指定要使用的Manifest文件。不指定的话,默认为default.xml文件
  • -b:指定要使用Manifest仓库中的某个特定分支。
  • --repo-url:指定repo的远端repoGit库的访问路径。
  • --no-repo-verify:指定不要验证repo源码。
  • --mirror:创建远程存储库的副本,而不是客户端工作目录。该选项用于创建版本库镜像。使用该选项则在下一步repo sync同步时,本地按照源的版本库组织方式进行组织,否则会按照 manifest.xml 指定的方式重新组织并检出到本地

修改获取repo的源码路径

前面已经说了下载下来的repo只是一个引导脚本,当执行repo init的时候才会下载repo的主体部分,并存放在当前目录的.repo/repo目录下。

这里就会涉及到一个问题,repo的主体部分是从哪里下载的?其实查看repo的引导脚本(/usr/local/bin/repo)可以发现,repo主体部分默认从https://gerrit.googlesource.com/git-repo获取(即,执行repo init命令时,不设置--repo-url选项),这个网站需要 科上学网 才可以访问。

解决该问题可以使用其他镜像源来获取,例如使用清华源。具体执行上有多种方式,下面列举两种方式供参考:
方式一:
每次执行repo init时,增加选项--repo-url=https://gerrit-googlesource.lug.ustc.edu.cn/git-repo

方式二:(建议)
设置环境变量REPO_URL,例如:

export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
bash

可以将环境变量写在启动脚本中(如,/etc/profile)

.repo文件夹简介

执行repo init命令之后,会在当前目录创建一个.repo文件夹。下面看看该文件夹下面都有什么东西吧。

$ tree .repo -L 1
.repo
├── manifests
├── manifests.git
├── manifest.xml
└── repo
bash

3 directories, file

文件夹描述
manifests manifest仓库(清单库)内容,即repo init-u选项对应的仓库
manifests.git manifest仓库(清单库)的.git目录
manifest.xml 指明当前生效的Manifest文件,即repo init-m选项对应的参数(没有该选项时默认为default.xml)
repo repo 命令的主体,包含了最新的 repo 命令

manifest文件介绍

所谓manifest仓库(清单库)其实就是存放manifest(清单)文件的仓库,实际上可以是任意仓库,只要该仓库中存在repo init命令-m选项指定的manifest文件即可,清单库命名为manifest只不过是一种约定俗成的写法罢了。

manifest仓库一般都会有一个default.xml文件,该文件为默认的manifest文件。

manifest文件格式

manifest文件是用XML文件的格式记录了本项目依赖的各个Git仓库的名称、地址,以及分支等信息。

下面举个实际的例子,看下manifest文件是什么样

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
    <remote fetch="ssh://git@git.software.team/learn-repo" name="origin" review="http://xxx.xxx.xxx:8080"/>
    <default remote="origin" revision="master" sync-j="4" />
    <project name="build" path="build">
        <linkfile dest="build.sh" src="build.sh"/>
    </project>
    <project name="docs" path="docs">
        <copyfile dest="README.md" src="README.md"/>
    </project>
    <project name="third_party/openssl" path="third_party/openssl" revision="OpenSSL_1_1_1l" />
    <project name="src" path="src" revision="release" />
</manifest>
xml

1. remote元素

  • fetch:使用此remote的所有项目的Git URL前缀。 每个项目的名称都附加到此前缀以形成用于克隆项目的实际 URL。如果使用此remote的所有项目的前缀和manifest仓库前置一致的话,可以使用..代替。
  • name:此清单文件唯一的短名称。此处指定的名称用作每个项目的 .git/config 中的远程名称,因此可自动用于 git fetchgit remotegit pull 和 git push 等命令。
  • review:通过repo upload将评论上传到的 Gerrit 服务器的主机名。 该属性是可选的; 如果未指定,则repo upload将不起作用

2. default元素

  • remote:project部分不单独指定remote的话就使用default部分的。
  • revision:project部分不单独指定revision的话就使用default部分的。
  • sync-j:同步时(执行repo sync命令时)使用的并行作业数

3. project元素
该部分定义了项目代码由哪些子仓库组成

  • name:相对于remote部分fetch指定的前缀的相对路径
  • path:把代码下载下来后在本地的相对于当前路径的相对路径
  • revision:是指下载下来的代码要checkout到哪个revision上,这里的revision可以是commit id、branch name、tag name,本质上都是commit id。default.xml中通常用branch name做revision,可以下载到并且checkout出该branch上最新的代码,标签和/或commit id在理论上应该有效,但尚未经过广泛测试。如果revision用commit id的话,那后面必须跟上upstream,upstream的值是个branch name。revision部分如果省略的话,就等于使用default部分定义的revision。

4. copyfile元素
project元素的子元素,每个元素描述了一对 src-dest 文件对。同步时(即执行repo sync命令时)src文件会被拷贝到dest。通常会被用于 README 或 Makefile 或其他构建脚本。
dest:是相对于当前目录(执行repo initrepo sync命令的目录)的路径
src:是相对于project path的相对路径

5. linkfile元素
copyfile类似,只不过不是拷贝,而是建立软连接。

更多关于manifest文件的格式的介绍,可以在repo init命令成功执行后,在代码根目录下的.repo/repo/docs下看到相关文档说明(问:不会写manifest文件,就无法创建清单库,从而无法执行repo init怎么办?答:找个开源清单库执行repo init即可,或者去github上下载一份repo的源码)。最简单的方式是直接去网站https://gerrit-googlesource.proxy.ustclug.org/git-repo/+/HEAD/docs/manifest-format.md查看帮助。

repo sync

命令格式:

repo sync [<project>...]
bash

初始化好一个 repo 工作目录后下一步就是把代码同步下来了,该命令用来下载新的更改并更新本地环境中的工作文件。如果您在未使用任何参数的情况下运行 repo sync,则该操作会同步所有项目(所有项目是指manifest文件中所有的project元素)的文件。

<project>:为manifest文件中project元素的name属性或者path属性的值。如果只需要同步某一个或者个别几个项目的话,就可以采用这种方法。

运行repo sync 后,将出现以下情况:

  • 如果目标项目从未同步过,则 repo sync 相当于 git clone。远程代码库中的所有分支都会复制到本地项目目录中。
  • 如果目标项目已同步过,则 repo sync 相当于以下命令:
    git remote update
    git rebase origin/<BRANCH>
    
    bash
    其中 <BRANCH> 是本地项目目录中当前已检出的分支。如果本地分支没有在跟踪远程代码库中的分支,则相应项目不会发生任何同步。
  • 如果 git rebase 操作导致合并冲突,那么您需要使用普通 Git 命令(例如 git rebase --continue)来解决冲突。

repo sync 运行成功后,指定项目中的代码会与远程代码库中的代码保持同步。

常用选项:

  • -d:将指定项目切换回清单修订版本。如果项目当前属于某个主题分支,但只是临时需要清单修订版本,则此选项会有所帮助。
  • -s:同步到当前清单中清单服务器元素指定的一个已知的良好版本。
  • -f:即使某个项目同步失败,系统也会继续同步其他项目。
  • -t:使用对应 tag 里的 manifest 文件
  • -m:手动指定当前操作使用哪个 manifest 文件
  • --force-sync:如果需要,强制覆盖现有的 git 目录指向不同的对象目录。此操作可能会导致数据丢失

repo start 创建主题分支

命令格式:

repo start <newbranchname> [--all | <project>...]
bash

创建并切换分支。刚克隆下来的代码是没有分支的repo start实际是对git checkout -b命令的封装。
为指定的项目或所有的项目(若使用-all),以清单文件中为设定的分支,创建特定的分支。

常用选项:

  • <newbranchname> 参数应简要说明您尝试对项目进行的更改。
  • <project> 指定了将参与此主题分支的项目。

注意:.是一个非常实用的简写形式,用来代表当前工作目录中的项目。

这条指令与git checkout -b 还是有很大区别的。

  • git checkout -b 是在当前所在的分支的基础上创建特性分支。
  • repo start 是在清单文件设定的分支的基础上创建特性分支。

repo status

命令格式:

repo status [<project>...]
bash

查看文件状态。对于每个指定的项目,将工作树与临时区域(索引)以及此分支 (HEAD) 上的最近一次提交进行比较。在这三种状态存在差异之处显示每个文件的摘要行。

要仅查看当前分支的状态,请运行 repo status。系统会按项目列出状态信息。对于项目中的每个文件,系统使用两个字母的代码来表示:

  • 在第一列中,大写字母表示临时区域与上次提交状态之间的不同之处。
    字母含义描述
    - 无更改 HEAD 与索引中相同
    A 已添加 不存在于 HEAD 中,但存在于索引中
    M 已修改 存在于 HEAD 中,但索引中的文件已修改
    D 已删除 存在于 HEAD 中,但不存在于索引中
    R 已重命名 不存在于 HEAD 中,但索引中的文件的路径已更改
    C 已复制 不存在于 HEAD 中,已从索引中的另一个文件复制
    T 模式已更改 HEAD 与索引中的内容相同,但模式已更改
    U 未合并 HEAD 与索引中的内容相同,但模式已更改
  • 在第二列中,小写字母表示工作目录与索引之间的不同之处。
    字母含义描述
    - 新/未知 HEAD 与索引中相同
    m 已修改 存在于索引中,也存在于工作树中(但已修改)
    d 已删除 存在于索引中,不存在于工作树中

两个表示状态的字母后面,显示文件名信息。如果有文件重名还会显示改变前后的文件名及文件的相似度。

repo checkout

命令格式:

repo checkout <branchname> [<project>...]
bash

切换分支。 实际上是对git checkout命令的封装,但不能带-b参数,所以不能用此命令来创建特性分支。
该命令等同于:repo forall [<project>...] -c git checkout <branchname>

repo branch

该命令等同于repo branches
命令格式:

repo branches [<project>...]
bash

汇总当前所有可用的主题分支。

repo diff

命令格式:

repo diff [<project>...]
bash

查看工作区文件差异。实际是对git diff命令的封装,用于分别显示各个项目或指定项目工作区下的文件差异。在 commit 和工作目录之间使用 git diff 显示明显差异的更改。

repo stage

命令格式:

repo stage -i [<project>...]
bash

把文件添加到index表中。实际上是对git add --interactive命令的封装,用于挑选各个项目中的改动以加入暂存区。

常用选项:

  • -i:表示git add --interactive命令中的--interactive,给出一个界面供用户选择。

repo forall

repo forall [<project>...] -c <command> [<arg>...]
bash

在每个项目中运行指定的 shell 命令。通过 repo forall 可使用下列额外的环境变量:

  • REPO_PROJECT:项目的名称。
  • REPO_PATH:项目在该工作区的相对路径。
  • REPO_REMOTE:项目远程仓库的名称。
  • REPO_LREV:manifest文件中revision属性,已转换为本地跟踪分支。如果您需要将manifest中revision值传递到某个本地运行的 Git 命令,则可使用此变量。
  • REPO_RREV:manifest文件中revision属性,与manifest文件中显示的名称完全一致。

常用选项:

  • -c:要运行的命令和参数,即shell命令。此命令会通过 /bin/sh 进行求值,它之后的任何参数都将作为 shell 位置参数传递。
  • -p:在指定命令输出结果之前显示项目标头。这通过以下方式实现:将管道绑定到命令的 stdin、stdout 和 sterr 流,然后通过管道将所有输出结果传输到一个页面调度会话中显示的连续流中。
  • -v:显示该命令向 stderr 写入的消息。

注意:shell指令中有上述环境变量时,则需要用使用单引号把shell命令括起来。

示例:

  1. 打印项目列表
    repo forall -c 'echo $REPO_PROJECT'
    
    bash
  2. 打印项目路径
    repo forall -c 'echo $REPO_PATH'
    
    bash

repo prune

命令格式:

repo download {[project] change[/patchset]}...
bash

删除已经合并分支。实际上是对git branch -d命令的封装,该命令用于扫描项目的各个分支,并删除已经合并的分支。

repo abandon

命令格式:

repo abandon [--all | <branchname>] [<project>...]
bash

删除指定分支。实际是对git brance -D命令的封装。

repo upload

命令格式:

repo upload [--re --cc] [<project>]...
bash

对于指定的项目,Repo 会将本地分支与最后一次 repo sync 时更新的远程分支进行比较。Repo 会提示您选择一个或多个尚未上传以供审核的分支。

注意:使用repo upload需要搭建gerrit环境,并且在manifest文件remote元素中添加review属性

您选择一个或多个分支后,所选分支上的所有提交都会通过 HTTPS 连接传输到 Gerrit。您需要配置一个 HTTPS 密码以启用上传授权。要生成新的用户名/密码对以用于 HTTPS 传输,请访问密码生成器

当 Gerrit 通过其服务器接收对象数据时,它会将每项提交转变成一项更改,以便审核者可以单独针对每项提交给出意见。要将几项“检查点”提交合并为一项提交,请使用 git rebase -i,然后再运行 repo upload

如果您在未使用任何参数的情况下运行 repo upload,则该操作会搜索所有项目中的更改以进行上传。

要在更改上传之后对其进行修改,您应该使用 git rebase -i 或 git commit --amend 等工具更新您的本地提交。修改完成之后,请执行以下操作:

  • 进行核对以确保更新后的分支是当前已检出的分支。
  • 对于相应系列中的每项提交,请在方括号内输入 Gerrit 更改 ID:
    # Replacing from branch foo
    [ 3021 ] 35f2596c Refactor part of GetUploadableBranches to lookup one specific...
    [ 2829 ] ec18b4ba Update proto client to support patch set replacments
    # Insert change numbers in the brackets to add a new patch set.
    # To create a new change record, leave the brackets empty.
    
    bash

上传完成后,这些更改将拥有一个额外的补丁程序集。

repo upload 相当于 git push,但是又有很大的不同。它将版本库改动推送到代码审核服务器(Gerrit软件架设)的特殊引用上。代码审核服务器会对推送的提交进行特殊处理,将新的提交显示为一个待审核的修改集,并进入代码审核流程,只有当审核通过后,才会合并到官方正式的版本库中。

常用选项:

  • -t:发送本地分支名称到Gerrit代码审核服务器
  • --re=REVIEWERS:要求指定的人员进行审核
  • --cc=CC:同时发送通知到如下邮件地址

repo download

命令格式:

repo download {[project] change[/patchset]}...
bash

从审核系统中下载指定更改,并放在您项目的本地工作目录中供使用。
例如,要将更改 23823 下载到您的平台/编译目录,请运行以下命令:

$ repo download platform/build 23823
bash

repo sync 应该可以有效移除通过 repo download 检索到的任何提交。或者,您可以将远程分支检出,例如 git checkout m/master

repo download命令主要用于代码审核者下载和评估贡献者提交的修订。
贡献者的修订在Git版本库中refs/changes//引用方式命名(缺省的patchset为1),和其他Git引用一样,用git fetch获取,该引用所指向的最新的提交就是贡献者待审核的修订。
使用repo download命令实际上就是用git fetch获取到对应项目的refs/changes//patchset>引用,并自动切换到对应的引用上。

repo grep

命令格式:

repo grep {pattern | -e pattern} [<project>...]
bash

打印出符合某个模式的行。相当于对 git grep 的封装,用于在项目文件中进行内容查找。

repo manifest

命令格式:

repo manifest [-o {-|NAME.xml}] [-m MANIFEST.xml] [-r]
bash

manifest检验工具,用于显示当前使用的manifest文件内容。

常用选项:

  • -r, --revision-as-HEAD:把某版次存为当前的HEAD
  • -o -|NAME.xml, --output-file=-|NAME.xml:把manifest存为NAME.xml

示例:

# 获取仓库的sha1值,并记录在一个新的release.xml文件中
repo manifest -o release.xml -r
bash

repo 工作流程

常用的 repo 工作流程如下:
在这里插入图片描述

repo sync后 git branch -a 显示中 “no branch” 和 “remotes/m/master” 的含义

使用repo工具同步代码之后,进入任意项目路径下,执行 git branch -a 输出如下:

$ git branch -a
* (no branch)
  remotes/m/master -> origin/dev
  remotes/origin/dev
  remotes/origin/master
bash
  1. 输出中的后两行比较好理解,就是该仓库的远程仓库里存在的分支。

  2. 输出的第一行 * (no branch) 中的 * 表示当前所在的分支,该行意思是,当前不再任何分支上。

    为什么会显示no branch 呢?
    repo sync 只是根据清单文件中 revision 版本进行更新的,没有固定的branch,repo sync 成功之后,不能直接进行操作,需要先执行 repo start 建立新的分支进行开发。

    其实,执行 repo branches 命令也会显示 no branches 的,这个就更好理解了,不同的子仓库的 revision 不尽相同,所有git仓库放在一起,更是没有一个确切的branch了。

  3. 输出的第二行中 remotes/m/master -> origin/dev 又是什么意思呢?

    • 前一部分表示 repo 清单库(manifest仓库)的分支,即执行 repo init 命令时 -b 选项的参数,如果执行 repo init 命令时没有指定 -b 选项,则表示默认采用清单库的master分支。
    • 箭头所指的后一部分 origin/dev,表示当前所使用的清单文件(.xml文件)里面指定的单个git库的revision值(即,清单文件中 project 元素的 revision 属性,如果 project 元素没有指定 revision 属性,则默认使用的是 default 元素的 revision 属性)。

    这样做的目的是:为了让用户方便的知道自己目前工作在清单库的哪个分支上。当前的清单库的这个分支又引用了当前git库的哪个branch/tag上

  4.  
 
 
 
 
 
 
 
 

 

it与Repo入门

收录于 · 英國程序員的IT技術分享
21 人赞同了该文章

如果您觉得本文对您有用,感谢留下您的赞赏!!多谢!!!

转自:

版本控制 - version control

  版本控制是什么已不用在说了,就是记录我们对文件、目录或工程等的修改历史,方便查看更改历史,备份以便恢复以前的版本,多人协作。。。

一、原始版本控制

  最原始的版本控制是纯手工的版本控制:修改文件,保存文件副本。有时候偷懒省事,保存副本时命名比较随意,时间长了就不知道哪个是新的,哪个是老的了,即使知道新旧,可能也不知道每个版本是什么内容,相对上一版作了什么修改了,当几个版本过去后,很可能就是下面的样子了:

如果您觉得本文对您有用,感谢留下您的赞赏!!多谢!!!

二、本地版本控制

  手工管理比较麻烦且混乱,所以出现了本地版本控制系统,记录文件每次的更新,可以对每个版本做一个快照,或是记录补丁文件。比如RCS。

 

广告
这本书能帮你成功转行
知乎自营
¥34.50
去购买​

三、集中版本控制

  但是本地版本控制系统偏向于个人使用,或者多个使用的人必须要使用相同的设备,如果需要多人协作就不好办了,于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生,比如Subversion,Perforce。

  在CVCS中,所有的版本数据都保存在服务器上,一起工作的人从服务器上同步更新或上传自己的修改。

 

  但是,所有的版本数据都存在服务器上,用户的本地设备就只有自己以前所同步的版本,如果不连网的话,用户就看不到历史版本,也无法切换版本验证问题,或在不同分支工作。。

  而且,所有数据都保存在单一的服务器上,有很大的风险这个服务器会损坏,这样就会丢失所有的数据,当然可以定期备份。

如果您觉得本文对您有用,感谢留下您的赞赏!!多谢!!!

 

四、分布式版本控制

  针对CVCS的以上缺点,出现了分布式版本控制系统( Distributed Version Control System,简称 DVCS ),如GIT,Mercurial。

  DVCS不是复制指定版本的快照,而是把所有的版本信息仓库全部同步到本地,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时push到相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,所以,只要有一个用户的设备没有问题就可以恢复所有的数据。

  当然,这增加了本地存储空间的占用。

一、获得GIT仓库

  有两种获得GIT仓库的方法,一是在需要用GIT管理的项目的根目录执行:

git init

  执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。

  另一种方式是克隆远程目录,由于是将远程服务器上的仓库完全镜像一份至本地,而不是取某一个特定版本,所以用clone而不是checkout(只取出一部分):

git clone <url>
广告
罗技G G502 HERO主宰者游戏鼠标 黑色
知乎
¥329.00
去购买​

二、GIT中版本的保存

  记录版本信息的方式主要有两种:

  1. 记录文件每个版本的快照
  2. 记录文件每个版本之间的差异

  GIT采用第一种方式。像Subversion和Perforce等版本控制系统都是记录文件每个版本之间的差异,这就需要对比文件两版本之间的具体差异,但是GIT不关心文件两个版本之间的具体差别,而是关心文件的整体是否有改变,若文件被改变,在添加提交时就生成文件新版本的快照,而判断文件整体是否改变的方法就是用SHA-1算法计算文件的校验和。

  GIT能正常工作完全信赖于这种SHA-1校验和,当一个文件的某一个版本被记录之后会生成这个版本的一个快照,但是一样要能引用到这个快照,GIT中对快照的引用,对每个版本的记录标识全是通过SHA-1校验和来实现的。

  当一个文件被改变时,它的校验和一定会被改变(理论上存在两个文件校验和相同,但机率小到可以忽略不计),GIT就以此判断文件是否被修改,及以些记录不同版本。

  在工作目录的文件可以处于不同的状态,比如说新添加了一个文件,GIT发觉了这个文件,但这个文件是否要纳入GIT的版本控制还是要由我们自己决定,比如编译生成的中间文件,我们肯定不想纳入版本控制。下面就来看下文件状态。

三、GIT文件操作

  版本控制就是对文件的版本控制,对于Linux来说,设备,目录等全是文件,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。

文件状态

  GIT仓库所在的目录称为工作目录,这个很好理解,我们的工程就在这里,工作时也是在这里做修改。

  在工作目录中的文件被分为两种状态,一种是已跟踪状态(tracked),另一种是未跟踪状态(untracked)。只有处于已跟踪状态的文件才被纳入GIT的版本控制。如下图:

 

  当我们往工作目录添加一个文件的时候,这个文件默认是未跟踪状态的,我们肯定不希望编译生成的一大堆临时文件默认被跟踪还要我们每次手动将这些文件清除出去。用以下命令可以跟踪文件:

git add <file>

  上图中右边3个状态都是已跟踪状态,其中的灰色箭头只表示untracked<-->tracked的转换而不是untracked<-->unmodified的转换,新添加的文件肯定算是被修改过的。那么,staged状态又是什么呢?这就要搞清楚GIT的三个工作区域:本地数据(仓库)目录,工作目录,暂存区,如下图所示:

 

  git directory就是我们的本地仓库.git目录,里面保存了所有的版本信息等内容。

  working driectory,工作目录,就是我们的工作目录,其中包括未跟踪文件及已跟踪文件,而已跟踪文件都是从git directory取出来的文件的某一个版本或新跟踪的文件。

  staging area,暂存区,不对应一个具体目录,其时只是git directory中的一个特殊文件。

  当我们修改了一些文件后,要将其放入暂存区然后才能提交,每次提交时其实都是提交暂存区的文件到git仓库,然后清除暂存区。而checkout某一版本时,这一版本的文件就从git仓库取出来放到了我们的工作目录。

文件状态的查看

  那么,我们怎么知道当前工作目录的状态呢?哪些文件已被暂存?有哪些未跟踪的文件?哪些文件被修改了?所有这些只需要一个命令,git status,如下图所示:

 

  GIT在这一点做得很好,在输出每个文件状态的同时还说明了怎么操作,像上图就有怎么暂存、怎么跟踪文件、怎么取消暂存的说明。

文件暂存

  在上图中我们可以很清楚地看到,filea未跟踪,fileb已被暂存(changes to be committed),但是怎么还有一个fileb是modified但unstaged呢?这是因为当我们暂存一从此文件时,暂存的是那一文件当时的版本,当暂存后再次修改了这个文件后就会提示这个文件暂存后的修改是未被暂存的。

  接下来我们就看怎么暂存文件,其实也很简单,从上图中可以看到GIT已经提示我们了:use "git add <file>..." to update what will be committed,通过

git add <file>...

  就可以暂存文件,跟踪文件同样是这一个命令。在这个命令中可以使用glob模式匹配,比如"file[ab]",也可以使用"git add ."添加当前目录下的所有文件。

取消暂存文件是

git reset HEAD <file>...

若修改了一个文件想还原修改可用

git checkout -- <file>...

查看文件修改后的差异

  当我们修改过一些文件之后,我们可能想查看我们都修改了什么东西,用"git status"只能查看对哪些文件做了改动,如果要看改动了什么,可以用:

git diff

  比如下图:

 

  ---a表示修改之前的文件,+++b表示修改后的文件,上图表示在fileb的第一行后添加了一行"bb",原来文件的第一行扩展为了修改后的1、2行。

  但是,前面我们明明用"git status"看到filesb做了一些修改后暂存了,然后又修改了fileb,理应有两次修改的,怎么只有一个?

  因为"git diff"显示的是文件修改后还没有暂存起来的内容,那如果要比较暂存区的文件与之前已经提交过的文件呢,毕竟实际提交的是暂存区的内容,可以用以下命令:

  /dev/null表示之前没有提交过这一个文件,这是将是第一次提交,用:

git diff --staged

  是等效的,但GIT的版本要大于1.6.1。

  再次执行"git add"将覆盖暂存区的内容。

忽略一些文件

如果有一些部件我们不想纳入版本控制,也不想在每次"git status"时看到这些文件的提示,或者很多时候我们为了方便会使用"git add ."添加所有修改的文件,这时就会添加上一些我们不想添加的文件,怎么忽略这些文件呢?

  GIT当然提供了方法,只需在主目录下建立".gitignore"文件,此文件有如下规则:

  • 所有以#开头的行会被忽略
  • 可以使用glob模式匹配
  • 匹配模式后跟反斜杠(/)表示要忽略的是目录
  • 如果不要忽略某模式的文件在模式前加"!"

  比如:

# 此为注释 – 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

移除文件

  当我们要删除一个文件时,我们可能就直接用GUI删除或者直接rm [file]了,但是看图:

 

  我们需要将文件添加到暂存区才能提交,而移除文件后是无法添加到暂存区的,那么怎么移除一个文件让GIT不再将其纳入版本控制呢?上图中GIT已经给出了说明:

git rm <file>...

  执行以上命令后提交就可以了,有时我们只是想将一些文件从版本控制中剔除出去,但仍保留这些文件在工作目录中,比如我们一不小心将编译生成的中间文件纳入了版本控制,想将其从版本控制中剔除出去但在工作目录中保留这些文件(不然再次编译可要花费更多时间了),这时只需要添加"--cached"参数。

  如果我们之前不是通过"git rm"删除了很多文件呢?比如说通过patch或者通过GUI,如果这些文件命名没有规则,一个一个地执行"git rm"会搞死人的,这时可以用以下命令:

 

移动文件

  和移除文件一样,移动文件不可以通过GUI直接重命令或用"mv"命令,而是要用"git mv",不然同移除文件一样你会得到如下结果:

 

  如果要重命名文件可以使用

git mv old_name new_name

  这个命令等效于

mv old_name new_name
git rm old_name
git add new_name

交互式暂存

  使用git add -i可以开启交互式暂存,如图所示,系统会列出一个功能菜单让选择将要执行的操作。

 

移除所有未跟踪文件

git clean [options] 一般会加上参数-df,-d表示包含目录,-f表示强制清除。

储藏-Stashing

  可能会遇到这样的情况,你正在一个分支上进行一个特性的开发,或者一个Bug的修正,但是这时突然有其他的事情急需处理,这时该怎么办?不可能就在这个工作进行到一半的分支上一起处理,先把修改的Copy出去?太麻烦了。这种情况下就要用到Stashing了。假如我们现在的工作目录是这样子的

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: index.html # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # # modified: lib/simplegit.rb

  此时如果想切换分支就可以执行以下命令

$ git stash Saved working directory and index state \ "WIP on master: 049d078 added the index file" HEAD is now at 049d078 added the index file (To restore them type "git stash apply")

  这时你会发现你的工作目录变得很干净了,就可以随意切分支进行其他事情的处理了。

  我们可能不只一次进行"git stash",通过以下命令可以查看所有stash列表

$ git stash list stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051... Revert "added file_size"

  当紧急事情处理完了,需要重新回来这里进行原来的工作时,只需把Stash区域的内容取出来应用到当前工作目录就行,命令就是

git stash apply

  如果不基参数就应用最新的stash,或者可以指定stash的名字,如:stash@{1},可能通过

git stash show

  显示stash的内容具体是什么,同git stash apply一样,可以选择指定stash的名字。

  git stash apply之后再git stash list会发现,apply后的stash还在stash列表中,如果要将其从stash列表中删除可以用

git stash drop

  丢弃这个stash,stash的命令参数都可选择指定stash名字,否则就是最新的stash。

  一般情况下apply stash后应该就可以把它从stash列表删除了,先apply再drop还是比较繁琐的,使用以下一条命令就可以同时完成这两个操作

git stash pop

  如果我们执行git stash时工作目录的状态是部分文件已经加入了暂存区,部分文件没有,当我们执行git stash apply之后会发现所有文件都变成了未暂存的,如果想维持原来的样子操持原来暂存的文件仍然是暂存状态,可以加上--index参数

git stash apply --index

  还有这么一种情况,我们把原来的修改stash了,然后修复了其他一些东西并进行了提交,但是,这些提交的文件有些在之前已经被stash了,那么git stash apply时就很可能会遇到冲突,这种情况下就可以在stash时所以提交的基础上新建一个分支,然后再apply stash,当然,这两个步骤有一人简单的完成方法

git stash branch <branch name>

四、提交与历史

  了解了文件的状态,我们对文件进行了必要的修改后,就要把我们所做的修改放入版本库了,这样以后我们就可以在需要的时候恢复到现在的版本,而要恢复到某一版,一般需要查看版本的历史。

提交

  提交很简单,直接执行"git commit"。执行git commit后会调用默认的或我们设置的编译器要我们填写提示说明,但是提交说明最好按GIT要求填写:第一行填简单说明,隔一行填写详细说明。因为第一行在一些情况下会被提取使用,比如查看简短提交历史或向别人提交补丁,所以字符数不应太多,40为好。下面看一下查看提交历史。

查看提交历史

  查看提交历史使用如下图的命令

 

  如图所示,显示了作者,作者邮箱,提交说明与提交时间,"git log"可以使用放多参数,比如:

 

  仅显示最新的1个log,用"-n"表示。

 

  显示简单的SHA-1值与简单提交说明,oneline仅显示提交说明的第一行,所以第一行说明最好简单点方便在一行显示。

  "git log --graph"以图形化的方式显示提交历史的关系,这就可以方便地查看提交历史的分支信息,当然是控制台用字符画出来的图形。

  "git log"的更多参数可以查看命令帮助。

不经过暂存的提交

 如果我们想跳过暂存区直接提交修改的文件,可以使用"-a"参数,但要慎重,别一不小心提交了不想提交的文件

git commit -a

  如果需要快捷地填写提交说明可使用"-m"参数

git commit -m 'commit message'

修订提交

  如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过"git add"添加到暂存区,然后执行以下命令:

git commit --amend

  然后修改提交说明覆盖上次提交,但只能重写最后一次提交。

重排提交

  通过衍合(rebase)可以修改多个提交的说明,并可以重排提交历史,拆分、合并提交,关于rebase在讲到分支时再说,这里先看一下重排提交。

  假设我们的提交历史是这样的:

 

如果我们想重排最后两个提交的提交历史,可以借助交互式rebase命令:

git rebase -i HEAD~2 或 git rebase -i 3366e1123010e7d67620ff86040a061ae76de0c8

  HEAD~2表示倒数第三个提交,这条命令要指定要重排的最旧的提交的父提交,此处要重排Second commit与Third commit,所以要指定Initial commit的Commit ID。如图所示:

 

  注释部分详细说明了每个选项的作用,如果我们想交互这两个提交,只需把开头的这两行交换下位置就OK了,交换位置后保存,然后看下提交历史:

 

  可以看到提交历史已经变了,而且最新的两个提交的Commit ID变了,如果这些提交已经push到了远程服务器,就不要用这个命令了。

删除提交与修改提交说明

 如果要删除某个提交,只需要删除相应的行就可以了,而要修改某个提交的提交说明的话,只需要把相应行的pick改为reward。

合并提交-squashing

  合并提交也很简单,从注释中的说明看,只需要把相应的行的pick改为squash就可以把这个提交全并到它上一行的提交中。

拆分提交

至于拆分提交,由于Git不可能知道你要做哪里把某一提交拆分开,把以我们就需要让Git在需要拆分的提交处停下来,由我们手动修改提交,这时要把pick改为edit,这样Git在处理到这个提交时会停下来,此时我们就可以进行相应的修改并多次提交来拆分提交。

撤销提交

  前面说了删除提交的方法,但是如果是多人合作的话,如果某个提交已经Push到远程仓库,是不可以用那种方法删除提交的,这时就要撤销提交

git revert <commit-id>

  这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。

Reset

  git reset会修改HEAD到指定的状态,用法为

git reset [options] <commit>

  这条命令会使HEAD提向指定的Commit,一般会用到3个参数,这3个参数会影响到工作区与暂存区中的修改:

  • --soft: 只改变HEAD的State,不更改工作区与暂存区的内容
  • --mixed(默认): 撤销暂存区的修改,暂存区的修改会转移到工作区
  • --hard: 撤销工作区与暂存区的修改

cherry-pick

  当与别人和作开发时,会向别人贡献代码或者接收别人贡献的代码,有时候可能不想完全Merge别人贡献的代码,只想要其中的某一个提交,这时就可以使用cherry-pick了。就一个命令

git cherry-pick <commit-id>

filter-branch

  这条命令可以修改整个历史,如从所有历史中删除某个文件相关的信息,全局性地更换电子邮件地址。

五、GIT分支

  分支被称之为GIT最强大的特性,因为它非常地轻量级,如果用Perforce等工具应该知道,创建分支就是克隆原目录的一个完整副本,对于大型工程来说,太费时费力了,而对于GIT来说,可以在瞬间生成一个新的分支,无论工程的规模有多大,因为GIT的分支其实就是一指针而已。在了解GIT分支之前,应该先了解GIT是如何存储数据的。

  前面说过,GIT存储的不是文件各个版本的差异,而是文件的每一个版本存储一个快照对象,然后通过SHA-1索引,不只是文件,包换每个提交都是一个对象并通过SHA-1索引。无论是文本文件,二进制文件还是提交,都是GIT对象。

GIT对象

  每个对象(object) 包括三个部分:类型,大小和内容。大小就是指内容的大小,内容取决于对象的类型,有四种类型的对象:"blob"、"tree"、 "commit" 和"tag"。

  • “blob”用来存储文件数据,通常是一个文件。
  • “tree”有点像一个目录,它管理一些“tree”或是 “blob”(就像文件和子目录)
  • 一个“commit”指向一个"tree",它用来标记项目某一个特定时间点的状态。它包括一些关于时间点的元数据,如提交时间、提交说明、作者、提交者、指向上次提交(commits)的指针等等。
  • 一个“tag”是来标记某一个提交(commit) 的方法。

  比如说我们执行了以下代码进行了一次提交:

$ git add README test.rb LICENSE2
$ git commit -m 'initial commit of my project'

  现在,Git 仓库中有五个对象:三个表示文件快照内容的 blob 对象;一个记录着目录树内容及其中各个文件对应 blob 对象索引的 tree 对象;以及一个包含指向 tree 对象(根目录)的索引和其他提交信息元数据的 commit 对象。概念上来说,仓库中的各个对象保存的数据和相互关系看起来如下图:

 

  如果进行多次提交,仓库的历史会像这样:

 

分支引用

  所谓的GIT分支,其实就是一个指向某一个Commit对象的指针,像下面这样,有两个分支,master与testing:

 

  而我们怎么知道当前在哪一个分支呢?其实就是很简单地使用了一个名叫HEAD的指针,如上图所示。HEAD指针的值可以为一个SHA-1值或是一个引用,看以下例子:

 

  git的所有版本信息都保存了Working Directory下的.git目录,而HEAD指针就保存在.git目录下,如上图所有,目前为止已经有3个提交,通过查看HEAD的值可以看到我们当前在master分支:refs/heads/master,当我们通过git checkout取出某一特定提交后,HEAD的值就是成了我们checkout的提交的SHA-1值。

  记录我们当前的位置很简单,就是能过HEAD指针,HEAD指向某一提交的SHA-1值或是某一分支的引用。

新建分支

git branch <branch-name>

  有时需要在新建分支后直接切换到新建的分支,可以直接用checkout的-b选项

git checkout -b <branch-name>

删除分支

git branch -d <branch-name>

  如果在指定的分支有一些unmerged的提交,删除分支会失败,这里可以使用-D参数强制删除分支。

git branch -D <branch-name>

检出分支或提交

  检出某一分支或某一提交是同一个命令

git checkout <branch-name> | <commit>

分支合并(merge)

  当我们新建一个分支进行开发,并提交了几次更新后,感觉是时候将这个分支的内容合回主线了,这是就可以取出主线分支,然后把分支的更新merge回来:

git checkout master
git merge testing

  如果master分支是testing分支的直接上游,即从master延着testing分支的提交历史往前走可以直接走到testing分支的最新提交,那么系统什么也不需要做,只需要改变master分支的指针即可,这被称之为"Fast Forward"。

  但是,一般情况是这样的,你取出了最新的master分支,比如说master分支最新的提交是C2(假设共3次提交C0<-C1<-C2),在此基础上你新建了分支,当你在分支上提交了C3、C5后想将br1时merge回master时,你发现已经有其他人提交了C4,这时候就不能直接修改master的指针了,不然会丢失别人的提交,这个时候就需要将你新建分支时master所在的提交(C2)后的修改(C4),与你新建分支后在分支上的修改(C3、C5)做合并,将合并后的结果作为一个新的提交提交到master,GIT可以自动推导出应该基于哪个提交进行合并(C2),如果没有冲突,系统会自动提交新的提交,如果有冲突,系统会提示你解决冲突,当冲突解决后,你就可以将修改加入暂存区并提交。提交历史类似下面这样(图来自Pro-Git):

 

  merge后的提交是按时间排序的,比如下图,我们在rename提交处新建分支test,在test上提交Commit from branch test,然后回到master提交commit in master after committing in branch,再将test分支merge进master,这时看提交提交历史,Commit from branch test是在commit in master...之前的,尽管在master上我们是在rename的基础上提交的commit in master...而GIT会在最后添加一个新的提交(Merge branch 'test')表示我们在此处将一个分支merge进来了。这种情况会有一个问题,比如说在rename提交处某人A从你这里Copy了一个GIT仓库,然后你release了一个patch(通过git format-patch)给A,这时候test分支还没有merge进来,所以patch中只包含提交:commit in master...然后你把test分支merge了进来又给了A一个patch,这个patch会包含提交:Commit from branch test,而这个patch是以rename为base的,如果commit in master...和Commit from branch test修改了相同的文件,则第二次的patch可能会打不上去,因为以rename为base的patch可能在新的Code上找不到在哪个位置应用修改。

 

分支衍合(rebase)

  有两种方法将一个分支的改动合并进另一个分支,一个就是前面所说的分支合并,另一个就是分支衍合,这两种方式有什么区别呢?

  分支合并(merge)是将两个分支的改动合并到一起,并生成一个新的提交,提交历史是按时间排序的,即我们实际提交的顺序,通过git log --graph或一些图形化工具,可能很明显地看到分支的合并历史,如果分支比较多就很混乱,而且如果以功能点新建分支,等功能点完成后合回主线,由于merge后提交是按提交时间排序的,提交历史就比较乱,各个功能点的提交混杂在一起,还可能遇到上面提到的patch问题。

  而分支衍合(rebase)是找到两个分支的共同祖先提交,将要被rebase进来的分支的提交依次在要被rebase到的分支上重演一遍,即回到两个分支的共同祖先,将branch(假如叫experiment)的每次提交的差异保存到临时文件里,然后切换到要衍合入的分支(假如是master),依次应用补丁文件。experiment上有几次提交,在master就生成几次新的提交,而且是连在一起的,这样合进主线后每个功能点的提交就都在一起,而且提交历史是线性的

  对比merge与rebase的提交历史会是下图这样的(图来自Pro-GIt):

(merge)

(rebase)

  rebase后C3提交就不存在了,取而代之的是C3',而master也成为了experiment的直接上游,只需一次Fast Forward(git merge)后master就指向了最新的提交,就可以删除experiment分支了。

衍合--onto

git rebase --onto master server client

  这条命令的意思是:检出server分支与client分支共同祖先之后client上的变化,然后在master上重演一遍。

父提交

  HEAD表示当前所在的提交,如果要查看当前提交父提交呢?git log查看提交历史,显然太麻烦了,而且输入一长串的Commit-ID也不是一个令人愉悦的事。这时可借助两个特殊的符号:~与^。

  ^ 表示指定提交的父提交,这个提交可能由多个交提交,^之后跟上数字表示第几个父提交,不跟数字等同于^1。

  ~n相当于n个^,比如~3=^^^,表示第一个父提交的第一个父提交的第一个父提交。

远程分支

  远程分支以(远程仓库名)/(分支名)命令,远程分支在本地无法移动修改,当我们clone一个远程仓库时会自动在本地生成一个名叫original的远程仓库,下载远程仓库的所有数据,并新建一个指向它的分支original/master,但这个分支我们是无法修改的,所以需要在本地重新一个分支,比如叫master,并跟踪远程分支。

  Clone了远程仓库后,我们还会在本地新建其他分支,并且可能也想跟踪远程分支,这时可以用以下命令:

git checkout -b [branch_name] --track|-t <remote>/<remote-banch>

  和新建分支的方法一样,只是加了一个参数--track或其缩写形式-t,可以指定本地分支的名字,如果不指定就会被命名为remote-branch。

  要拉取某个远程仓库的数据,可以用git fetch:

git fetch <remote>

  当拉取到了远程仓库的数据后只是把数据保存到了一个远程分支中,如original/master,而这个分支的数据是无法修改的,此时我们可以把这个远程分支的数据合并到我们当前分支

git merge <remote>/<remote-branch>

  如果当前分支已经跟踪了远程分支,那么上述两个部分就可以合并为一个

git pull

  当在本地修改提交后,我们可能需要把这些本地的提交推送到远程仓库,这里就可以用git push命令,由于本地可以由多个远程仓库,所以需要指定远程仓库的名字,并同时指定需要推的本地分支及需要推送到远程仓库的哪一个分支

git push <remote> <local-branch>:<remote-branch>

  如果本地分支与远程分支同名,命令可以更简单

git push <remote> <branch-name> 等价于 git push <remote> refs/heads/<branch-name>:refs/for/<branch-name>

  如果本地分支的名字为空,可以删除远程分支。

  前面说过可以有不止一个远程分支f,添加远程分支的方法为

git remote add <short-name> <url>

六、标签-tag

  作为一个版本控制工具,针对某一时间点的某一版本打tag的功能是必不可少的,要查看tag也非常简单,查看tag使用如下命令

git tag

  参数"-l"可以对tag进行过滤

git tag -l "v1.1.*"

Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。

  轻量级标签只需在git tag后加上tag的名字,如果tag名字

git tag <tag_name>

  含附注的标签需要加上参数-a(annotated),同时加上-m跟上标签的说明

git tag -a <tag_name> -m "<tag_description>"

如果你有自己的私钥,还可以用 GPG 来签署标签,只需要把之前的 -a 改为 -s(signed)

  查看标签的内容用

git show <tag_name>

  验证已签署的标签用-v(verify)

git tag -v <tag_name>

  有时在某一个版本忘记打tag了,可以在后期再补上,只需在打tag时加上commit-id

  要将tag推送到远程服务器上,可以用

git push <remote> <tag_name>

  或者可以用下面的命令推送所有的tag

git push <remote> --tags

七、Git配置

  使用"git config"可以配置Git的环境变量,这些变量可以存放在以下三个不同的地方:

  • /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system选项,读写的就是这个文件。
  • ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global选项,读写的就是这个文件。
  • 当前项目的 git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖/etc/gitconfig 中的同名变量。

  在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings\$USER。此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。

  最基础的配置是配置git的用户,用来标识作者的身份

git config --global user.name <name>
git config --global user.email <email>

  文本编辑器也可以配置,比如在git commit的时候就会调用我们设置的文本编辑器

git config --global core.editor vim

  另一个常用的是diff工具,比如我们想用可视化的对比工具

git config --global merge.tool meld

  要查看所有的配置,可以用

git config --list

  或者可以在git config后加上配置项的名字查看具体项的配置

git config user.name

  作为一个懒人,虽然checkout、status等命令只是一个单词,但是还是嫌太长了,我们还可以给命令设置别名如

git config --global  checkout

  这样git co就等于git checkout

  前面说地,git配置项都保存在那3个文件里,可以直接打开相应的配置文件查看配置,也可以直接修改这些配置文件来配置git,想删除某一个配置,直接删除相应的行就行了

 

八、其他

  关于GIT各命令的说明可以查看相关帮助文档,通过以下方法:

git help <command>或git <command> --help

REPO

repo start <topic_name>

  开启一个新的主题,其实就是每个Project都新建一个分支。

repo init -u <url> [OPTIONS]

  在当前目录下初始化repo,会在当前目录生生成一个.repo目录,像Git Project下的.git一样,-u指定url,可以加参数-m指定manifest文件,默认是default.xml,.repo/manifests保存manifest文件。.repo/projects下有所有的project的数据信息,repo是一系列git project的集合,每个git project下的.git目录中的refs等目录都是链接到.repo/manifests下的。

repo manifest

  可以根据当前各Project的版本信息生成一个manifest文件

repo sync [PROJECT1...PROJECTN]

  同步Code。

repo status

  查看本地所有Project的修改,在每个修改的文件前有两个字符,第一个字符表示暂存区的状态。

-no changesame in HEAD and indexAaddednot in HEAD, in indexMmodifiedin HEAD, modified in indexDdeletedin HEAD, not in indexRrenamednot in HEAD, path changed in indexCcopiednot in HEAD, copied from another in indexTmode changedsame content in HEAD and index, mode changedUunmergedconflict between HEAD and index; resolution required

  每二个字符表示工作区的状态

lettermeaningdescription-new/unknownnot in index, in work treemmodifiedin index, in work tree, modifiedddeletedin index, not in work tree

repo prune <topic>

  删除已经merge的分支

repo abandon <topic>

  删除分支,无论是否merged

repo branch或repo branches

  查看所有分支

repo diff

  查看修改

repo upload

  上传本地提交至服务器

repo forall [PROJECT_LIST]-c COMMAND

  对指定的Project列表或所有Project执行命令COMMAND,加上-p参数可打印出Project的路径。

repo forall -c 'git reset --hard HEAD;git clean -df;git rebase --abort'

  这个命令可以撤销整个工程的本地修改。

posted @ 2025-12-11 09:53  前沿风暴  阅读(22)  评论(0)    收藏  举报

校内网 © 2004-2025

京公网安备 33010602011771号 浙ICP备2021040463号-3