zoukankan      html  css  js  c++  java
  • git整理

    git特点:
    1- 直接记录快照,而非差异比较。以快照流的方式对待数据。对所有文件制作一个快照,保存这个快照的索引。如果文件没有改动,git只是简单保留一个链接指向之前存储的文件。
    2- 近乎所有操作都是本地执行,所以很快。例如svn如果断网了就无法提交。

    git三种状态:
    已提交(committed): 修改进入了本地数据库中
    已修改(modified): 修改了,但未保存到数据库中
    已暂存(staged): 将修改的文件快照放入暂存区等待提交

    git三个区域概念(Working tree, staging area, and Git directory):
    git仓库目录(.git):git用来存储项目元数据和对象数据库的地方
    工作目录: git仓库的压缩数据库中提取出来的某个版本
    暂存区: 是一个保存了待提交文件的信息,放在git仓库目录中

    HEAD的概念:
    HEAD就是指向当前分支的最后一个提交的指针
    HEAD可以简写成@。    HEAD~N表示顺着自己这一脉(主线,git log --graph的左边)上溯N个提交。  HEAD^表示上溯一个提交(等效于HEAD^1,这里的1表示主线,2表示被合并的提交<假设存在,git log --graph的右分支>), HEAD^^^表示主线上溯3个提交(等效于HEAD^^^1)。

    获取帮助:
    git help <verb>     #例如git help config
    git <verb> --help
    man git-<verb>

    获取一个仓库(repository):
    途径1: 克隆远程仓库。 执行git clone <remote_repo> [directory]会从服务器仓库上拉取源码文件的所有版本
    途径2: 初始化一个本地仓库。在有源码的目录中执行git init命令初始化一个仓库,在目录下会生成.git仓库目录。此时没有任何文件被跟踪


    基本流程:
    1-修改文件
    2- git add <pathspec>...                     # 跟踪<pathspec>指定的目录或文件,也就是将它们纳入版本控制。同时这些文件也进入了暂存区,等待提交。
    3- git commit -m "初始化工程"           #提交到本地git仓库(也就修改的快照进入.git仓库目录)

    注意 git add 命令是个多功能命令。1-可以用它开始跟踪新文件; 2-把已跟踪的文件放到暂存区; 3-还能用于合并时把有冲突的文件标记为已解决状态...等功能。
               git commit是将暂存区的快照提交到git仓库
               所以,执行git add后,修改的快照进入了暂存区待commit,如果此时又修改了文件,那么修改还在工作区中,需要再次git add才能将新的修改放入暂存区。

    配置:
    git配置文件可以使用git config命令来读写:
           1.   /etc/gitconfig 作用于系统级 git config 加 --system选项时读写此文件
           2.  ~/.gitconfig 或 ~/.config/git/config 作用于当前用户 git config 加 --global选项时读写此文件
           3.  当前仓库目录下的.git/config 作用于当前仓库目录对应的仓库 工作目录是该仓库,且git config 不加参数时,读写此文件
    每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。

    重要命令
    git config --list                         #列出当前配置
    git config <key>                      # 查看某项配置,例如 git config core.editor
    git config <key> <value>        # 修改某项配置,例如: git config --global core.editor vim

    远程仓库操作:

    git clone -b master https://a.cn/x/y.git      # 只克隆master分支(对于很大的仓库或网速很慢时挺有用的)
    git remote -v                                            # 查看远程分支, 加-v参数不但显示远程仓库短名字,还显示它的长名字。 origin是git clone给远程仓库默认生成的短名字,长名字就是那串长长的url:https://a.com/foo/bar
    git remote show origin                             # 查看远程仓库origin的所有远程分支,这条命令可以查看本地分支跟踪的是哪个远程分支。(设置跟踪参考下面git push -u的说明)
    git branch -r                                            # 列出远程仓库的所有分支以及远程仓库的默认分支是哪个(例如origin/HEAD->origin/master)。 “git ls-remote [远程仓库短名字]” 也是类似功能的命令
    git remote add <远程短名字> <url>         # 关联远程仓库(远程仓库存在的情况下才执行这条命令)。一个本地仓库可以关联多个远程仓库
    git fetch origin  dev:Dev                          #  从远程仓库origin下载数据,指定远程仓库的dev下载到对应本地仓库Dev。语法: git fetch   <远程短名>  [远程分支][:本地分支]   直接执行git fetch会从默认追踪的远程分支下载
    git pull                                                     # 是git fetch 和git merge的组合,参数指定方式参考上面的git fetch,我通常不适用git pull , 而是git fetch,然后再git merge。
    git push origin  LB:rb                              # 推送本地分支LB到远程仓库origin的rb分支。如果远程仓库origin没有rb分支,则会在远程origin下新建一个rb分支。如果直接执行git push那么就将本地分支推送到默认的远程仓库。如果本地仓库关联多个远程仓库,可以直接执行git push fooRep来指定将本地分支的变更推送到远程仓库fooRep下。如果推送的时候,提示没有对应的上游分支可以增加-u选项(--set-upstream选项的缩写)来建立对远程分支的跟踪,一旦使用-u来跟踪远程分支了,后面直接git push,不用跟其他参数了。这里我们执行git remote show origin就会看到本地的LB追踪了远程仓库origin的rb分支
    git push --all origin                                 # 不管本地是否存在对应的origin远程分支,都会将本地的所有分支都推送到远程主机.
    git rename origin gitee_foo                    # 把远程仓库名origin重命名为gitee_foo
    git remote rm gitee_foo                         # 删除远程仓库,也可以: git push origin --delete dev //假设远程仓库短名是origin
    注意: 一般而言,dev、debug之类的分支是不需要推送到远程仓库的,一般是把这些分支合并到master分支后,推送master到远程仓库

     

    分支操作:
    git branch                                                      #查看分支 -v 或 -vv会显示详细信息
    git branch --merged                                      #查看所有已合并的分支, 同理 --nomerged查看所有未合并的分支
    git branch <branchName>                            #创建分支
    git branch <brName> <commitID>                #以某个commitID来创建分支,非常有用
    git checkout <branchName>                         #切换分支, 加-b参数标示创建并切换分支
    git checkout origin/br0                                  #对于远程clone下来的仓库origin,切换到它的br0分支
    git checkout -b <local-br> <remote>/<br>     #创建一个与远程分支remote/br相对应的本地分支  #针对特定标签建分支
    git checkout -b <brName> <tag>                  #针对特定标签建分支
    git merge <branchName>                             #合并分支到当前分支。 通常合并分支时,git一般使用”Fast forward”模式,禁用FF模式,需要加参数--no-ff ( 非FF合并后的历史有分支,能看出来曾经做过合并,而FF看不出来)
    git branch –d <branchName>                       #删除分支-D表示强制
    git branch -u <remote>/<brName>               # 设置已有的本地分支来跟踪一个刚刚拉取下来的远程分支。 -u的长选项格式是--set-upstream-to。 此时@{u}或@{upstream}是<remote>/<brName>的快捷方式。所以git merge @{u}相当于git merge <remote>/<brName>
    git push origin --delete branch1                  #删除远程分支, 也可以写成 git push origin :branch1 

     注意master分支应该是非常稳定的,一般不在上面干活。在dev分支上干活,然后将稳定了的dev分支合并到master分支。团队协作是各个成员将自己分支不断合并到dev分支。

    工作进度隐藏:
    git stash save "stash_comment"       #保存完成一半的工作, 此时git status提示是干净的。
    git stash list                                       #列出已经隐藏的git栈
    git stash apply stash@{N}                 #恢复到stash N
    git stash clear                                   #清除缓存的stash
    git stash pop                                     #将stash从git栈中弹出
    git drop stash@{N}                           #删除某个stash
    git stash show stash@{N}                #查看某个stash

    比较差异:
    git diff   [<path>...]                                         #使用默认对比工具来比较
    git difftool   [<path>...]                                   #使用第三方工具比较差异, 例如BeyondCompare。关于将beyondCompare用于git,参考另一篇文章 
    git diff/difftool [file]                                         #对比工作区和暂存区的差别(git add之前的)
    git diff/difftool --staged [file]                           #对比暂存区和上次commit的差别
    git diff/difftool  <commit-id> <commit-id>       #比较两个版本(用commit-id指定)的差异
    git diff/difftool HEAD  [file]                              #比较工作区和最后一次commit的差异
    git diff/difftool  master  ReadMe.txt                #比较当前分支和master分支的ReadMe.txt文件的差异 
    git log dev ^master                                        # 比较dev分支有,而master分支没有的提交
    git log master..dev                                        # dev比master多了哪些提交? ..可以理解为from->to
    git log master...dev                                       # 不知道谁的提交多,只是想比较有哪些提交差异.加--left-right 参数可以显示提交所属的分支是哪个(例如git log --left-right master...dev 的<箭头表示master的)
    git whatchanged <file>                                 # 查看某个文件的变更的详细提交记录,简单记录可以使用git log --pretty=oneline  <file>。 查看完后,可以git show <commit-id> [file]或者git difftool <commit-id1> <commit-id2> [file]来查看具体变更
    git blame <file>                                             # 显示文件的每一行最后变更的commit id

    撤销修改 / 版本回退 :
    git  checkout  --  ReadMe.txt proto.c          #从暂存区中恢复文件到工作区。也就是执行add之前反悔了。这里的"--"表示选项的结束,如果没有任何选项,可以省略 "--"
    git  reset  --soft  <commit-id>                     # HEAD移动到 commit-id 指定的那个提交(不是针对单个文件或目录,所以参数中不能跟路径),也可以用HEAD~N的方式来指定重置到前N个版本。
    git  reset --hard  <commit-id>                    #HEAD暂存区工作区都重置到commit-id指定的提交(不是针对单个文件或目录,所以参数不带路径)。这个有点危险,如果误操作,只能通过git reflog 查一下历史操作的commit-id才能恢复
    git reset  --mixed  <commit-id>   [path]      #HEAD暂存区都重置到commit-id指定的提交,工作区不变, --mixed是默认选项,参数可以带路径(可以针对单个文件或目录执行重置)
    我测试的结果:   --soft是只重置HEAD指针, 工作区和暂存区不变。 不能带路径。
                               --hard是HEAD、暂存区和工作区都重置(危险操作) 。不能带路径。
                               --mixed是重置HEAD和暂存区(默认参数)。 工作区不变。可以带路径,但是带路径会有warning

    git revert  <commit-id>         #revert和reset的区别是,revert是将旧版本变成一个新的提交.  可以revert常规commit也可以revert分支合并的commit, 后者需要-m <1|2> 来指定保留哪个分支,1表示当前分支
    例如下面revert合并的commit:
    --A------B-----C------M----X----Y(revert)
       -----a-----b-------/
    如果当前处于上面分支X状态(此时上面分支有AaBbCX的提交), 如果Y处执行git revert -m 1 M的CommitID    则上面的分支只有ABCX的提交,(也就是丢弃了ab的提交)
                                                                                              如果Y处执行git revert -m 2 M的CommitID    则上面的分支只有AabX的提交(也就是丢弃了BC的提交). 注意这条命令是在Y处执行,而非上一条命令执行完后执行

    revert注意的地方,可以到https://segmentfault.com/a/1190000012897697看例子

    修改已完成的提交(commit后,可以多次修改该commit):
    例如:
    git add proto.c
    git commit -m '修正proto.c的bug' #突然发现漏了proto.h和gen_id.c,忘了移除tmp.txt,于是执行:
    git add proto.h gen_id.c
    git rm tmp.txt
    git commit --amend '修正proto.c和gen_id.c的bug' #此时git log --stat 只能看到修改后的提交

    删除文件:
    git rm <file> ; git commit -m 'xxxx'                   #删除工作区和暂存区文件,并且提交
    git rm --cached <file> ; git commit -m 'xxx'      #删除暂存区文件,并提交。此时工作区文件还在,这是版本库不再跟踪它了。

      

    查看提交历史:
    git log -3 #查看最近三次提交
    git log --after/before='1999-09-09'          #查看1999-09-09前/后的提交。 指定时间可以使用类似"1year"、“8days”之类的。 --after等同--since,--before等同于--until
    git log --author/--committer=<name>      #按作者/提交者查看,注意作者和提交者的区别
    git log --grep=<pattern>                          #按正则搜索注释
    git log hello.c                                          # 查看修改了hello.c的commit,查看针对某个路径的commit,如果有很多选项时,可以使用 -- 标示选项结束: liru
    git log --graph                                         #形象显示commit log
    git log --stat                                            #显示commit 历史涉及的文件
    git show --stat [commitID]                      #显示某个commit涉及的文件变更
    git log --pretty=format:%h" "%an" "%s    #显示短hash、作者、注释(空格分隔)。更多%号格式参考git lot help
    git log --pretty=oneline                           #单行显示commit历史
    git log  --  server.c                                  # 查看 server.c 的提交记录

    标签:
    git  tag                                                                                                   # 查看已有标签
    git  tag  -l  'v1.*'                                                                                     # -l是小写的L,只列出 v1.* 的版本号, 批配处v1.0 v1.1 v1.2...
    git  tag   v1.0                                                                                         # 打一个轻量级标签, 轻量级标签是对某个提交的引用。不指明commit-id的情况下,默认引用HEAD
    git  tag  -a   v2.0  -m '这是v2.0附注标签的说明'                                     # 打上一个附注标签,-a是的a是annoted的首字母。附注标签是一个仓库中的独立对象。它有自身的校验和信息,以及标签说明。
    git  tag  -s    v2.1 -m '这是v2.0附注标签的说明'                                     # 打上一个GPG签名的附注标签。 -s是signed的首字母. 使用git show v2.1会看到GPG签名
    git  show  v2.0                                                                                       # 查看标签v2.0的详情
    git  tag  -v  v2.1                                                                                     # 验证含有GPG签名的标签(keyring中需要有GPG公钥)
    git  tag  v1.2   df1796d00a50a5567fac0b7d689402942943e01d         # 给df1796d00a50a5567fac0b7d689402942943e01d这个提交打轻量标签
    git tag -a v2.3 -m '忘记打标签了'                                                           # 给df1796d00a50a5567fac0b7d689402942943e01d这个提交打附注标签
    git  push origin  v2.3                                                                             # 将标签推送到远程仓库origin。(默认情况下git push是不会推送标签的,所以需要专门推送标签,标签才能体现在远程仓库上)
    git  push  origin  --tags                                                                          # 将所有标签推送到远程仓库

    ------------------------------------ 注意力分割线 --------------------------------------

    我做的小测试:
    mkdir x; cd x
    git init
    git remote add ts2 https://gitee.com/xxx/test2
    git fetch ts2                                       # 抓取的副本在本地的工作空间是看不到文件的。ps: 可以git fetch ts2 dev 只fetch dev分支
    git checkout -b dev ts2/dev              #此时就可以看到ts2/dev对应的的本地dev分支了。此时执行 ls -l 就能看到工作空间有文件了
    上面的最后两步可以这么玩:
    git fetch ts2 dev:dev      #fetch ts2的dev分支,并在本地创建dev分支
    git checkout dev            #切换到本地dev分支,此时就能看到远程的ts2/dev分支在本地对应dev分支的工作空间文件了

    git checkout -b dev2      #建立本地dev2分支
    git push -u ts2 dev2      #把本地分支dev2 推送到远程分支ts2上,结果在gitee服务器上看到了dev2分支

  • 相关阅读:
    寒假学习5流程控制之ifelse与for循环
    寒假学习4scala数据类型与运算符
    寒假学习13
    寒假学习14
    寒假学习3scala简介与基础1
    sqlserver 定时自动备份
    windows mysql 主从同步
    mysql 连接数 最大并发数
    mysql基础语法
    sqlserver 常见语法
  • 原文地址:https://www.cnblogs.com/mind-water/p/git.html
Copyright © 2011-2022 走看看