Git简介 & 实操大全

 【前言】

Git简介:

Git(读音为/gɪt/)是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理,也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。差不多是以前SVN工具的进阶版。

插话 - 关于Git & Gerrit & Repo & Gitlab & Github:

Android使用Git作为代码管理工具,并开发了Gerrit进行代码审核以便更好的对代码进行集中式管理,还开发了Repo命令行工具(Repo是谷歌用Python脚本写的调用git的一个脚本),对Git部分命令封装,将百多个Git库有效的进行组织。

继Gerrit之后,广泛使用的GitLab是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。具有wiki和issue跟踪功能。安装方法参考GitLab在GitHub上的Wiki页面。

而GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。

Gerrit简介:

1). 基于 Web 的代码评审和项目管理的工具,面向基于 Git 版本控制系统;
2). 为 Git 引入强制性的代码审核机制,非特别的授权设置,向 Git 版本库的推送(Push)必须要经过 Gerrit服务器,经过审核流程后,才能正式纳入代码库;
3). 每一次提交将对应一个评审任务;
4). 通过特殊的分支提交评审任务(refs/for/….); 
5). Gerrit 提供的 Git 服务的端口并非标准的 22 端口,缺省是 29418 端口;
6). Gerrit缺省的Http端口是8080。


Repo简介:

Repo工具实际上是由一系列的Python脚本组成的,这些Python脚本通过调用Git命令来完成自己的功能。比较有意思的是,组成Repo工具的那些Python脚本本身也是一个Git仓库。这个Git仓库在AOSP里面就称为Repo仓库。我们每次执行Repo命令的时候,Repo仓库都会对自己进行一次更新。

上面我们讨论的是Repo仓库,但是实际上我们执行Repo命令想操作的是AOSP。这就要求Repo命令要知道AOSP都包含有哪些子项目,并且要知道这些子项目的名称、仓库地址是什么。换句话说,就是Repo命令要知道AOSP所有子项目的Git仓库元信息。我们知道,AOSP也是不断地迭代法变化的,例如,它的每一个版本所包含的子项目可能都是不一样的。这意味着需要通过另外一个Git仓库来管理AOSP所有的子项目的Git仓库元信息。这个Git仓库在AOSP里面就称为Manifest仓库。

到目前为止,我们提到了三种类型的Git仓库,分别是Repo仓库、Manifest仓库和AOSP子项目仓库。Repo仓库通过Manifest仓库可以获得所有AOSP子项目仓库的元信息。有了这些元信息之后,我们就可以通过Repo仓库里面的Python脚本来操作AOSP的子项目。那么,Repo仓库和Manifest仓库又是怎么来的呢?答案是通过一个独立的Repo脚本来获取,这个Repo脚本位于AOSP的一个官方网站上,我们可以通过HTTP协议来下载。

现在,我们就通过一个图来来勾勒一下整个AOSP的Picture,它由Repo脚本、Repo仓库、Manifest仓库和AOSP子项目仓库组成,如图1所示:

Git简介 & 实操大全_第1张图片

Gitlab简介:

略。 

Github简介:

略。

Git工作原理示意图:

Git简介 & 实操大全_第2张图片

【Git实操大全】

序号

操作场景

操作时机

GIT + Gerrit(or Gitlab)
(git:代码管理工具;gerrit/gitlab: 代码审核管理工具)

Repo
(repo: 封装git的命令行工具;)

命令

说明

命令

说明

一、基本操作:

增、删、改、查

       
1.1 环境配置 配置公钥 ssh-keygen -t rsa -C "[email protected] 生成rsa类型的非对称密钥,并添加一个comments。ssh key 一般在
~/.ssh/id_rsa.pub 文件内。
   
  配置用户名 git config --global user.name "shaoyoushi"      
    配置邮件 git config --global user.email "[email protected]"      
    修改manifest仓库分支信息 修改.repo/manifests下真正的manifest文件***.xml  表面上调用的.repo/manifest.xml其实是个链接,查看实际链到的.xml后,修改该具体的.xml即可。    
1.2 本地建仓,初始化 新建并初始化空仓 git init 进入新建的本地工作目录后,下载git或repo工具并初始化,会在本地生成.git或.repo(内含仓库信息),类似SVN上的.svn。 repo init 初始化git仓库,如“repo init -u git://172.16.1.11/manifest.git -b 分支名称 -m wanglei.xml”
1.3 拉代码 获取库上代码 git clone 中心库地址
例如:git clone ssh://[email protected]:2222/m00524372/soundeffectehb.git
克隆中心库到本地,不指定本地库名则克隆到本地的库名默认和中心库一致。
关于中心库的地址,Git 支持许多数据传输协议。可以使用git:// 协议、 http(s):// 或者 user@server:/path.git 表示的 SSH 传输协议。
更新所有工程代码:
repo sync(sync之前先repo init,下载repo并克隆manifest仓)
如果版本库尚不存在,则执行repo sync 命令相当于执行git clone;如果项目版本库已经存在,则相当于执行下面的两条指令:
git remote update
(相当于对每一个remote源执行了fetch操作)
git rebase origin/branch
(针对当前分支的跟踪分支执行rebase操作。)
  git fetch 远端库名称
例如:git fetch kirin
获取远端库的更新到本地库(但不更新工作拷贝)。    
  git fetch 远端库名称
git checkout origin/master -- path/to/file
先从远端库更新到本地库,然后从本地库更新单个文件到本地拷贝。    
  更新指定工程代码:
git pull <中心库地址> <远端库分支>:<本地分支>
取回远程主机某个分支的更新,再与本地的指定分支合并(相当于先做git fetch,再做git merge)。如果是本地当前分支合并,则冒号后的部分都可以不输入。 repo forall -c git checkout -b  本地分支名称(自定义)  中心库分支名称 实际是一个迭代器操作。
1.4 建分支 创建本地分支 git branch 新分支名 注:若在分支名后加上commitID则表示是基于该commitID拉出的新分支。 创建本地分支:
repo start 分支名 --all
创建分支。repo start实际是对git checkout –b 命令的封装。为指定的项目或所有项目(若使用—all参数),以清单文件中为设定的分支,创建特性分支。
  切换到某个已存在的工作分支 git checkout 分支名   repo checkout   […] 切换分支。实际上是对git checkout 命令的封装,但不能带-b参数,所以不能用此命令来创建特性分支。
  创建并且切换到本地分支 git checkout -b local_branch      
  删除本地分支 git branch -d  分支名 注:”-d”只删除已合并到其他分支的部分。删除分支前会检查分支中的内容是否都已经合并到其他分支,如果没有,则命令不执行;”。 repo prune […] 实际上是对git branch –d命令的封装,该命令用于扫面项目的各个分支,并删除已经合并的分支。
  git branch -D 分支名 注:”-D”不进行检查,直接删除分支。 删除本地分支:
repo abandon […]
实际上是对git branch –D 命令的封装。
  创建远程分支 步骤一:
创建本地分支,并切换到新建的本地分支工作
步骤二:
git push  远程版本库名 本地分支名
     
  删除远程分支 git remote rm 远端库目标   repo remote rm 远端库目标 删除远端库上的指定目标。Repo remote命令用于设置远端库,类似的还有“repo remote add 目标 远端库URL”
  分支合并 场景1:直接合并"分支1"到"分支2":
步骤一:切换工作空间到"分支2"
git checkout "分支2"
步骤二:合并
"git merge ""分支1""

场景2:挑选合并某次commit到当前分支:
步骤一:切换到目标分支
步骤二:git cherry-pick commitID"
  两个分支进行Merge
情景假设:把分支branch_511的从最开始 到 某个tag 的所有改动merge到分支branch_513
0.创建本地branch_511分支
  repo forall -c 'git checkout -b branch_511 origin/hw/sz/jb/k3v2-es1-4.1.1_r1/sbox_ar511_pdt'
 
1.查看有无本地改动(有改动要把改动回退掉)
  repo status
 
2.把分支branch_511更新到想merge的tag(标签)
例如更新到tag 511_V200R005C31B020_20141001071613
repo forall -c 'git reset --hard 511_V200R005C31B020_20141001071613'

3.创建本地branch_513分支
 repo forall -c 'git checkout -b branch_513 origin/hw/sz/jb/k3v2-es1-4.1.1_r1/sbox_ar513_pdt'
 
4.把分支branch_511的改动merge到分支branch_513
  repo forall -c 'git merge --no-squash --no-ff --no-commit  branch_511'
 
5.查看branch_513的改动
        repo status

6.确认无误后把有改动的分支进行上库操作
先提交
repo forall -c 'git commit -m "merge branch_511 to branch_513 (511_V200R005C31B020_20141001071613)"'
然后上中心库:
repo upload

7.到网站进行review,保证更改生效
http://rnd-arandroid.huawei.com:8080/#/q/status:open,n,z
 
  重命名分支 git branch -m oldbranch newbranch 注:此操作是将“oldbranch”分支的名称改成“newbranch”。如果需要拉出分支,并同时切换到新分支可以用“git checkout –b oldbranch newbranch”    
1.5 修改代码 添加单个文件的修改 git add 文件名 添加某个文件 repo stage -i […] 把文件添加到index表中。实际是对git add --interactive命令的封装、用于挑选各个项目工作区中的改动以加入暂存区。
    添加整个目录的修改 git add .   添加当前目录    
    提交到本地库 git commit -m "新的提交信息" --amend 此操作将所有缓存区的修改提交到本地版本库,同时可添加comments注释。
注:此操作只能修改最新的一次提交,之前的提交无法修改。
同git  
    修改最近一次提交的注释 git commit --amend 注意:必须是最近提交,还没有push并且merged的注释。    
    新建标签 git tag -a 标签 -m 标签信息 用 -a (译注:取 annotated 的首字母)指定标签名字,而 -m 选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中。另外,还可通过其他命令参数添加标签签署信息,便于校验。 tag  
    为指定提交增加tag git tag tag_name a_commit_id  对当前分支的指定提交打一个tag    
    删除tag git tag -d a_tag_name      
    跟踪(add)时忽略某些文件 在工作目录下新建一个名为.gitignore的文件,然后在里面规定忽略那些文件 详见:http://rnd-isourceb.huawei.com/help/huawei_help/progit/zh/02-git-basics/01-chapter2    
    删除文件 git rm 文件名 删除文件并将删除的信息转移至缓存区,要想删除库上的文件需要执行commit操作,同样使用git reset 恢复删除文件。 同git  
    重命名文件或目录 git mv 原文件名 新文件名 重命名或者移动本地文件或目录,mv后直接到缓存区,需要执行commit操作。    
    新增修改至本地缓存(暂存区) git stash 保存工作区现场,并将工作区置为clean状态。每次保存,最新的stash都被命名为stash@{0},而之前的保存的stash的命名都会加1,也就是说stash的保存类似于stack,是FILO的。
注:此操作是将本地未提交的修改暂存起来,并将文件状态恢复到HEAD,如果要恢复暂存的修改,运行“git stash pop ”即可,如果要恢复指定的stash修改则用git stash pop stash@{1} // 从指定的一个stash恢复,并删除该stash。
   
    保存至暂存区时添加说明 git stash save "message"   保存一个stash,并附加一条说明消息到这个stash上,方便后面的查看    
1.6 提交 提交代码到中心库 git push <远端库名称> <本地分支名(或HEAD)>:<远端分支名>
例如:git push ssh://[email protected]:2222/m00524372/soundeffectehb.git HEAD:master
注1:此操作是将本地库的修改同步到中心库,如果本地分支的名称和远程分支的名称相同,则远程分支名称可省略。
注2:gerrit不允许直接将本地修改同步到远程仓库。客户机必须先push到远程仓库的refs/for/*分支上,等待审核。这也是为什么我们需要使用gerrit的原因。gerrit本身就是个代码审核工具。因此需要使用以下命令提交:git push ics(or origin) HEAD:refs/for/br_ICSV_1.0.0_develop_20190817
repo upload

注解:
我们产品代码通过gerrit和repo禁用掉了直接用git push来上库
只能通过repo  upload  project_name 把修改上传到 “伪库”,必须经过代码review才可以真正”漂白”上库,共享给主线.
repo upload相当于git push,但是又有很大的不同。它不是将版本库改动推送到克隆时的远程服务器,而是推送到代码审核服务器(Gerrit软件架设)的特殊引用上,使用SSH协议。代码审核服务器会对推送的提交进行特殊处理,将新的提交显示为一个待审核的修改集,并进入代码审查流程,只有当审核通过后,才会合并到官方正式的版本库中。
git push   将本地当前分支推送到相关联的远程仓库中去。需要通过以下操作预先关联一个远程库:
在本地添加远程库
git remote add name url    // 在本地添加关联一个远程仓库
git remote add origin [email protected]:shaoyoushi/hello-world.git    // 在本地添加关联一个远程库,命名为origin(习惯),采用的是ssh协议进行传输
git remote add abc https://github.com:shaoyoushi/hello-world.git        // 在本地添加关联一个远程库,命名为abc,采用的是https协议进行传输
   
推送tag到远程仓库 git push origina_tag_name(推送一个指定的tag到远程仓库origin)
git push origin --tags(推送所有未推送的tags到远程仓库origin)
  创建tag
repo forall -c 'git tag -a tag_name -m "创建tag的原因和描述" '
repo forall -c ' git push origin tag_name '

删除tag
repo forall -c 'git tag -d tag_name'

回退代码到某个tag(只读)
repo forall -c ' git checkout  tag_name '

回退代码到某个tag(可写)
repo forall -c 'git checkout -b new_branch_name tag_name'
 
把另一个分支的修改合并到当前分支 git checkout mywork
git rebase origin
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 为最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。参考:https://blog.csdn.net/hudashi/article/details/7664631/    
1.7 查看库配置信息 查看manifest内容     repo manifest –o xml文件 显示manifest文件内容。
  查看git版本号 git version 显示git版本号。 repo version 显示repo版本号。
  查看单个git配置信息 例如:git config user.name 显示user.name的配置信息。    
  查看git配置列表信息 git config --list 有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig和~/.gitconfig),不过最终 Git 实际采用的是最后一个。    
查看分支信息 查看分支 git branch (或直接查看.git/HEAD中的内容,即为当前HEAD指针所指向的内容) 查看git库中的所有分支,后面加参数“-r”则可显示git库中对应的远程分支参照。 repo branches  
  查看指定分支信息 git show a_branch      
  查看对应的远程分支 git branch -r      
  查看本地关联的远程仓库 git remote      // 查看远程仓库的名称
git remote -v  // 查看远程参考的名称和对应的url
     
  更新绑定的远端库路径 git remote set-url 远端库名称 远端库新地址
例如:git remote set-url gitlab ssh://[email protected]:2222/ics/icsv100/audiosoundeffects/audiocontrol.git
当远端库地址更新时通过该操作重新绑定,否则会push失败。    
  查看分支合并记录 git branch --merged 查看已经合并到当前分支的所有分支。    
  git branch --no-merged 查看还没有合并到当前分支的所有分支。    
查看修改提交信息 查看当前仓下文件状态 git status 修改完之后,查看本地库中所有文件的状态,包括未受控的,已修改,已缓存。冲突文件的状态也表现为已修改的。 repo status (可选加参数:文件,目录,分支) 实际上是对git diff-index、git diff-filse命令的封装,同时显示暂存区的状态和本地文件修改的状态。
会输出显示该项目分支的修改状态:
1.每个小节的首行显示项目名称,以及所在分支的名称
2.第一个字母表示暂存区的文件修改状态
 -:没有改变
 A:添加(不在HEAD中,在暂存区中)
 M:修改(在HEAD中,在暂存区中,内容不同)
 D:删除(在HEAD中,不在暂存区)
 R:重命名(不在HEAD中,在暂存区,路径修改)
 C:拷贝(不在HEAD中,在暂存区,从其他文件拷贝)
 T:文件状态改变(在HEAD中,在暂存区,内容相同)
 U:未合并,需要冲突解决
3.第二个字母表示工作区文件的更改状态
 -:新/未知(不在暂存区,在工作区)
 m:修改(在暂存区,在工作区,被修改)
 d:删除(在暂存区,不在工作区) 4.两个表示状态的字母后面,显示文件名信息。如果有文件重名还会显示改变前后的文件名及文件的相似度
  查看log git log --all    (查看全部详细的log信息)
git log --pretty=oneline //查看当前分支的提交历史 里面包含 commit id    (查看全部log概要列表)
查看日志 同git  
  统计所有提交者各自的代码行数 git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --since ==2019-11-01 --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done      
  查看命令历史 git reflog      
  查看所有的stash git stash list      
  查看指定提交信息 git show a_commit_id      
  显示图形化的git日志树 gitk --all 显示图形化的git日志树,并可在相关版本号上新建分支(需安装Xming图形化显示操作工具)。gitk是用 Tcl/Tk 写成的,基本上相当于 git log 命令的可视化版本,凡是 git log 可以用的选项也都能用在 gitk 上。在项目工作目录中输入 gitk 命令后,就会启动它。    
查看标签信息 查看所有tag标签 git tag 列出所有已有的标签。也可按照正则表达式列出指定的部分标签。    
  查看指定tag信息 git show 已知标签 可以看到在提交对象信息上面,列出了此标签的提交者和提交时间,以及相应的标签说明。    
  分享标签 git push 中心库 --tags 默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。--tags可一次把所有本地新增标签都推送上去。    
1.8 恢复 清除未跟踪(未add)文件 git checkout -- filename或git checkout . 恢复工作区文件(如果暂存区有文件就从暂存区恢复,否则从仓库恢复)    
  清除所有未跟踪(未add)文件 git clean -dxf 清除所有未跟踪文件,包括纳入.gitignore中的文件。    
  撤销已修改(已add)文件

git reset HEAD <文件路径> 

注:HEAD指针总是指向分支的最新提交。每当你做出了一个提交,HEAD更新为最新提交。HEAD树枝存储在.git/refs/heads/ 目录中。

     
  恢复本地工作区内容(相对于本地版本库):已经修改,且已经add,未commit,回退整套代码到最近一次提后的状态

git reset --hard HEAD(or commitID)

注:全球版本号(commitID):Git库的版本号是通过SHA-1算法根据库中的所有内容计算出一个40位的哈希值,这个哈希值是全球唯一的,基本只要前六位就可以唯一标识了。
注:该操作将回退本地所有文件到当前最新提交节点,包括本地内容。

参数 --hard 表示删除自该次提交后所有的修改记录(未跟踪文件除外),如果需要保留目前的修改,则使用--soft参数。    
  回退到某一历史版本 git revert commitID 注:此操作将回退记录到历史的某一节点,并作为一次新的提交到库中。    
1.9 比较 比较内容区别 git diff OldCommitID NewCommit ID(前6位) 比较文件/目录下所有文件修改前后的不同。
注:新添加的文件使用git diff的时候不能显示。
repo diff 目标1 目标2 repo diff实际是对git diff 命令的封装,用于分别显示各个项目工作区下的文件差异。只看着两个目标的区别。
  git diff 比较本地的与缓存的区别 repo diff  查看所有项目的区别。
  git diff --cached 比较缓存的与本地库中的区别
同git
 
  git diff commitID1 commitID2 --文件名 对比该文件在特定commit之间的区别 同git  
  git diff [filename] 查看文件变化    
1.10 构建 发起构建时 -   repo build CommitID branch 构建通过就可以正式合入到中心库了。
1.11 查看帮助 查看帮助文档 git help   repo help  
  查看某个命令的帮助文档 git CMD -help (CMD为add、log等实际命令)   repo CMD -help (CMD为sync、diff等实际命令)  
二、其他操作        
2.1 获取历史版本   整个工作区切换到历史版本:
git checkout 
检出某文件的历史版本:
git checkout --
  1、生成标签文件(当确定某一版本需要打标签)
repo manifest -r -o 标签名.xml
2、将标签文件提供给CMO存放在manifest.git中
3、按标签获取:
repo init -u ssh://10.141.105.217/platform/manifest.git -m tag名称.xml
 
2.2 调用图形化界面   git gui 添加、修改、删除文件时,可以直接通过“git gui”命令,
调出图形界面,通过“Stage Changed”缓存文件(新添加
的文件只能通过git add 命令缓存),在提交信息处输入“提
交信息”,然后通过“Commit”提交。
   
2.3 迭代器操作       repo forall […] –c 迭代器操作,可以在所有指定的项目中执行同一个shell指令。熟练使用的话功能很强大。-c:后面所带的参数着是shell指令。例如:repo forall -c pwd(遍历所有的git仓库,并在每个仓库执行-c所指定的命令(被执行的命令不限于git命令,而是任何被系统支持的命令,比如:ls 、 pwd 、cp 等)。
2.4 代码审核下载       repo download {project change [patchset]}… 主要用于代码审核者下载和评估贡献者提交的修订。

你可能感兴趣的:(git)