Git笔记

作者: ahuustcly | 来源:发表于2018-09-11 00:10 被阅读52次

    一.Git简介

    Git是世界上最先进的分布式版本控制系统,相对于SVN这样的集中式版本控制系统,Git不需要“中央服务器”,每一台电脑都有一个完整的版本库。因此,它的安全性要高很多。Git一般工作流程如下:

    • 克隆 Git 远程资源库作为工作目录
    • 在克隆的资源库上添加或修改文件
    • 如果其他人修改了,则需要相应更新资源
    • 在提交前查看修改
    • 提交修改
    • 修改完成后,若发现错误,撤回提交并再次修改并提交

    Git支持Linux/Mac OS/Windows,可根据需求自行安装。安装后需要做如下配置:

    • /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。
    • ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。
    • 当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。
        每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。根据需要,配置相应的工作环境变量如用户名、邮箱等。

    二.版本管理

    Git文件状态

      Git中的文件被分为两种状态,一种是已跟踪状态(tracked),另一种是未跟踪状态(untracked)。只有处于已跟踪状态的文件才被纳入GIT的版本控制,已跟踪状态的文件又分为未修改、已修改、暂存状态,如上图所示。

    Git的工作区域

      Git中的工作区域又分为三个:工作区、暂存区、版本库(仓库)

    • 工作区
      就是在电脑中能看到的目录
    • 暂存区
      stage或者index,存放在.git目录下的index文件中
    • 版本库
      工作区有一个隐藏的目录.git,即git的版本库,又名仓库(repository)。简单理解成一个目录,是Git用来跟踪和管理版本库的。工作区所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
    1. 创建仓库
      步骤1:创建一个空目录,如“mkdir git;cd git”
      步骤2: git init
      创建完成后,在当前目录下生成一个隐藏目录.git

    2. 添加文件
      步骤1:创建文件readme.txt
      步骤2:git add readme.txt,将文件写入暂存区
      步骤3:git commit -m "wrote a readme file",将暂存区所有添加到仓库中。(-m 为本次提交说明)

    3. 查看状态
      步骤1:git status,获取仓库当前的状态
      步骤2:git diff,查看文件修改的内容

    4. 版本回退
        Git每一次的commit提交为“保存一个快照”,一旦把文件改乱了,或者误删了文件,还可以从其中的一个commit恢复。
      步骤1:git log,显示从最近到最远的提交日志
      步骤2:git reset --hard HEAD^,回退到上一个版本
      注:在Git中,用HEAD表示当前版本,也就是最新的提交,上一个版本就是HEAD^,依次类推;也可用git log显示出来的commit id来标识版本回退(--hard撤销工作区域与暂存区的修改)
      步骤3:要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本

    5. 修改文件
        工作区中新建的文件,git status查看时为“Untracked files”状态,当提交到版本库并修改后,
      步骤1:git status,状态为“Changes not staged for commit”
      步骤2:git add再git commit
      注:git commit只会把提交到暂存区的修改,加入到commit中
      步骤3:如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过"git add"添加到暂存区,然后执行git commit --amend,覆盖上一次提交

    6. 撤销修改
      步骤1:git checkout -- file,可以丢弃工作区的修改(注意“--”非常重要,否则表示切换分支)。存在下面几种情况:

      • 修改后没有存入暂存区,可以直接回到和版本库一样
      • 已经添加到暂存区,但未修改,用命令git reset HEAD <file>(即取消暂存),就回到前面1场景
      • 已经添加到暂存区,又做了修改,撤销修改就回到了添加到暂存区后的状态
      • 若修改已经提交到了版本库,则参考前面“版本回退”
    7. 删除文件
      步骤1:使用rm 删除工作区的文件
      步骤2:有两种情况

      • 情况一:从版本库中删除,即git rm然后提交git commit
      • 情况二:删除错了,git checkout -- test.txt将文件恢复到当前版本(注意不要忘了"--")

    三.远程仓库

    可以自己搭建Git服务器作为远程仓库,也可以使用已有的代码托管服务网站,如GitHub、码云等。

    1. GitHub
      1.1 配置环境
      步骤1:ssh-keygen -t rsa -C "youremail@example.com"生成公私钥(在用户主目录下 "cd ~");生成的公私钥主要用于加密通信内容以及身份校验,私钥自己保留,公钥提供给GitHub
      步骤2:登陆GitHub,打开“Account settings”,“SSH Keys”页面:点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容

      1.2 添加远程仓库

      • 步骤1:登陆GitHub,在右上角找到“Create a new repo”按钮,创建一个新的空的仓库;然后,可以从这个仓库在本地克隆出新的仓库,也可以把一个已有的本地仓库与之关联
      • 步骤2:在本地的仓库下运行git remote add origin git@github.com:xxx.git;其中origin是远程库的名字,git@github.com:xxx.git是步骤1创建的远程仓库;使得本地仓库与远程仓库关联
      • 步骤3:git push -u origin master,将本地库的所有内容推送到远程库上(-u主要是第一次推送,指定origin为默认主机,后续推送时则不需要)

      1.3 从远程库克隆

      • 步骤1:类似于1.2中的步骤1,在GitHub网站上创建远程仓库,如名字叫gitskills
      • 步骤2:从远程库克隆,git clone git@github.com:xxx/gitskills.git,这样就在本地目录下克隆了一份远程库。Git支持多种协议,如默认的ssh(git://),以及http、https等

      1.4 使用GitHub参与开源项目

      • 在GitHub上,可以Fork任意开源仓库;
      • 自己拥有Fork后的仓库的读写权限,然后在本地克隆一个Fork后的仓库;
      • 可以推送pull request给官方仓库来贡献代码

    2.自己搭建Git服务器

    • 步骤1:安装Git,sudo apt-get install git
    • 步骤2:创建用户,sudo adduser git
    • 步骤3:创建证书登录,收集需要登录的用户的公钥,把用户公钥导入到/home/git/.ssh/authorized_keys文件中
    • 步骤4: 初始化Git仓库,sudo git init --bare sample.git;修改用户sudo chown -R git:git sample.git防止其他用户修改
    • 步骤5:禁用shell登录,通过编辑/etc/passwd文件完成
    • 步骤6:本地仓库克隆git clone git@server:/srv/sample.git

    3.码云

    四.分支管理

    1. 创建和合并分支
        在Git里,默认为主分支即master,而HEAD指向当前的分支。一开始master指向最新的提交,而HEAD指向master;当创建并切换到分支dev后,dev指向与master相同的提交,并且HEAD指向dev。当在新的分支dev上提交时,dev指针向前移动,master不变。
    • git checkout -b dev,创建并切换到分支dev
    • git branch,查看分支
    • git branch <name>,创建分支
    • git checkout <name>,切换分支
    • git merge <name>,合并某分支到当前分支
    • git branch -d <name>,删除分支
    1. 解决冲突



        当把feature1分支的修改自动合入master分支时,可能会产生冲突。Git会在文件中使用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们手工修改后再提交。

    2. 分支管理策略


    • master分支主要用来发布版本,比较稳定
    • 团队在dev分支上工作,dev分支是不稳定的,等到某个版本稳定时,再合入master分支
    • 个人在自己的分支下开发工作,如michael、bob等,再不断的往dev分支上合入代码
    1. Bug分支
        当你在dev分支上的开发进行到一半时,需要在master分支上去修复一个紧急的Bug。第一步就需要先切换到master 分支。但当你执行 $ git checkout master 命令的时候,会提示出错,需要将当前的分支修改提交后才能切换。怎么办?

      • 步骤1:git stash,将当前工作现场储藏起来
      • 步骤2:git checkout master,切换到主分支并创建bug分支来修复问题
      • 步骤3:修复完成后,切回主分支并合并修改,然后删除bug分支
      • 步骤4:切换至dev分支,git checkout dev,并执行git stash list查看,git stash pop恢复现场并删除储藏(或者git stash apply stash@{0}恢复,但是恢复后,stash内容并不删除,用git stash drop来删除)
    2. 多人协作

    • 克隆远程库,同时执行git checkout -b dev origin/dev,创建远程库的dev分支到本地
    • 试图用git push origin <branch-name>推送自己的修改;
    • 若推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;git pull --rebase origin master,rebase是通过将local commit一个一个地在更新后的master分支上运行;git add <conflicted-files>;git rebase --continue
    • 如果合并有冲突,则解决冲突,并在本地提交;
    • 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功
    • 如果git pull提示no tracking information,则说明本地分支和远程分支的连接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
      关于Git的工作流请参考:深入理解学习Git工作流
    1. Rebase
        rebase的目的是把本地未push的分叉提交历史整理成直线,使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

      • 步骤: git rebase

      有两种方法将一个分支的改动合并进另一个分支,一个就是前面所说的分支合并,另一个就是分支衍合,这两种方式有什么区别呢?
        分支合并(merge)是将两个分支的改动合并到一起,并生成一个新的提交,提交历史是按时间排序的,即我们实际提交的顺序,通过git log --graph或一些图形化工具,可能很明显地看到分支的合并历史,如果分支比较多就很混乱,而且如果以功能点新建分支,等功能点完成后合回主线,由于merge后提交是按提交时间排序的,提交历史就比较乱,各个功能点的提交混杂在一起。


      分支合并

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


      分支衍合

    git rebase -i HEAD ~ 2,HEAD~2表示倒数第三个提交,这条命令要指定要重排的最旧的提交的父提交。

    1. cherry-pick
        当与别人和作开发时,会向别人贡献代码或者接收别人贡献的代码,有时候可能不想完全Merge别人贡献的代码,只想要其中的某一个提交,这时就可以使用cherry-pick了。就一个命令
      git cherry-pick <commit-id>
        一般通过在gerrit中粘贴相应的命令,直接在提交的目录下执行这个命令

    五.标签管理

    tag是一个容易让人记住的有意义的名字,与某个commit绑定在一起

    • 切换到需要打标签的分支是,执行git tag <tagname>
    • 查看所有的标签,git tag
    • 历史提交打标签,git tag <tagname> commit_id
    • 查看标签信息,git show <tagname>
    • 删除标签,git tag -d <tagname>
    • 推送某个标签到远程,使用命令git push origin <tagname>
    • 一次性推送全部尚未推送到远程的本地标签git push origin --tags

    六.其它

    1. 忽略特殊文件
        Git工作区的根目录下创建一个.gitignore文件,把要忽略的文件名填进去,Git就会自动忽略这些文件。忽略文件的是:

      • 忽略操作系统自动生成的文件,如缩略图等;
      • 忽略编译生成的中间文件、可执行文件等,如.class .o文件;
      • 忽略私有的带有敏感信息的配置文件

      忽略的规则是:

      • 所有以#开头的行会被忽略
      • 可以使用glob模式匹配
      • 匹配模式后跟反斜杠(/)表示要忽略的是目录
      • 如果不要忽略某模式的文件在模式前加"!"
    2. Git跟踪限制
        目前的版本控制系统只能跟踪文本文件如网页、txt、程序源代码等,视频图片等二进制文件,Git无法知道具体改动细节

    参考:
    Git手册
    https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137402760310626208b4f695940a49e5348b689d095fc000
    http://www.runoob.com/git/git-remote-repo.html

    相关文章

      网友评论

        本文标题:Git笔记

        本文链接:https://www.haomeiwen.com/subject/pffdgftx.html