zoukankan      html  css  js  c++  java
  • Git使用入门

    这篇笔记是我看尚硅谷的教程边看教程边总结下来的,有些地方写的很浅,应该之后会慢慢补充

    git同SVN一样,也是一个版本控制软件,实现了版本控制软件具有的「协同修改」、「数据备份」、「权限控制」、「历史记录」、「分支管理」等功能

    git最大的优势是拥有SVN没有的「对团队外开发者贡献的代码进行合并审核」的功能,这使得不仅是团队成员而是所有人都可以参与到项目中,这也是GitHub等网站现在如此流行的原因

    Git 结构

    git分为本地库和远程库,其中远程库在代码托管中心上,可以是GitHub、码云,或者我们自己建的GitLab私服

    之前工作也只是在一个master分支下改动,没有用到git最强大的分支管理功能,每次也只是「提交并推送」,可以说和SVN没有区别

    这个流程是个轮廓,不保证细节全部准确

    Git 本地库

    git 在本地库有3个区域,分别是:工作区(working tree)、暂存区(index)、本地仓库

    graph LR 工作区 -- 1: git add --> 暂存区 暂存区 -- 2: git commit --> 本地仓库

    Git 远程库

    如果这个库只是团队内成员操作:

    graph TD 组长 -- 1 git push 将初始版本提交远程库 --> 代码托管中心 代码托管中心 -- 2 git clone 克隆初始化本地仓库 --> 程序员1 程序员1 -- 3 git push 提交修改的代码 --> 代码托管中心 代码托管中心 -- 4 git pull 拉取程序员的改动 --> 组长

    如果是跨团队协作就稍微复杂一些:

    graph TD 组长 -- 1 git push 将初始版本提交远程库 --> 代码托管中心 代码托管中心 -- 2 GitHub fork --> 开发者的托管中心 开发者的托管中心 -- 3 git clone 克隆初始化本地仓库 --> 开发者 开发者 -- 4 git push 提交自己的修改 --> 开发者的托管中心 开发者的托管中心 -- 5 GitHub pull request 合并请求 --> 代码托管中心 代码托管中心 -- 6 组长审核请求并merge --> 组长

    Git 基本操作

    config 设置签名

    要使用git首先需要在config中设置签名,签名中的邮箱可以是不存在的,这个只是为了分辨哪个人提交的

    config有2个级别,仓库级/全局

    • 仓库级,仓库级的优先级比全局高,保存在当前 .git 目录下的 config 文件
    $ git config user.name "n031"
    $ git config user.email "n031@gmail.com"
    
    • 全局,在家目录(Linux 上是"~")下的 .gitconfig 文件
    $ git config --global user.name "n031"
    $ git config --global user.email "n031@gmail.com"
    

    add commit 本地库基本操作

    $ git init
    

    初始化成功后在目录下会生成一个 .git 隐藏文件

    查看当前仓库状态

    $ git status
    On branch master 
    # 在maste 分支
    No commits yet 
    # 还没有提交记录[本地库]
    nothing to commit (create/copy files and use "git add" to track) 
    # 也没有什么可提交的(创建/复制文件 并且使用 git add 让 git 去追踪[管理]这个文件)[暂存区,放入暂存区就是被git所追踪]
    

    创建一个good.txt文件,然后再查看状态

    $ git status
    On branch master
    No commits yet
    Untracked files:
    # 未被追踪文件
      (use "git add <file>..." to include in what will be committed)
            good.txt
    
    nothing added to commit but untracked files present (use "git add" to track)
    

    现在暂存区是空的,将good.txt添加进去

    $ git add good.txt
    warning: LF will be replaced by CRLF in good.txt. 
    # 自动替换成CRLF,如果从windows down下来还是LF
    The file will have its original line endings in your working directory
    
    $ git status
    On branch master
    No commits yet
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
            new file:   good.txt
    

    可以将文件从暂存区移除

    git rm --cached good.txt
    

    或者提交到本地仓库

    # git commit -m "本次注释" <可选文件名>
    $ git commit -m "add good.txt" good.txt
    [master (root-commit) c0adbbe] add good.txt 
    # root-commit根提交,只有一次
     1 file changed, 1 insertion(+) 
     # 1个文件被修改,增加了1行
     create mode 100644 good.txt
     # 仓库创建了ood.txt文件
    
    $ git status
    On branch master
    nothing to commit, working tree clean
    

    修改good.txt状态后再查看状态

    $ git status
    On branch master
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      # 将修改添加到暂存区
      (use "git restore <file>..." to discard changes in working directory) 
      # 撤销工作区中的修改
      # 之前的版本是git checkout ?
            modified:   good.txt
    
    no changes added to commit (use "git add" and/or "git commit -a")
    

    git add good.txt后查看状态,ps:这里假如把good.txt删除了,然后git rm good.txt也可以把删除这个操作提交到暂存区

    $ git status
    On branch master
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
      # 撤销添加到暂存区的修改
      # 之前的版本是reset HEAD,删除暂存区全部修改
            modified:   good.txt
    

    这之中用到的操作

    $ git add good.txt # 添加good.txt的修改,工作区->暂存区
    $ git rm good.txt # 仅删除good.txt时,添加good.txt的修改,工作区->暂存区
    $ git restore good.txt # 如果工作区和暂存区不同,工作区恢复成暂存区的版本
    $ git restore --staged good.txt # 如果工作区和暂存区不同,暂存区恢复成工作区的版本
    

    大致猜测暂存区起到一个标准的作用,与工作区对比的作用,让工作区不直接和版本库比较,一些“尝试的改动”比较时就更直观容易也更容易恢复

    log 查看版本记录

    最基础的:git logB查看上一页,Space查看下一页,Q退出

    比较简洁且常用的:git log --pretty=onelinegit log --oneline,两种结果相同,

    log只显示HEAD之后的版本,不显示之前的版本(后面会提到)

    git reflog也可以查看版本日志,比git log多距离当前HEAD几跳的信息

    reset 版本前进后退

    • 基于索引值版本重置
    $ git reflog
    126320d (HEAD -> master) HEAD@{0}: reset: moving to 126320d
    f9752a6 HEAD@{1}: reset: moving to @
    f9752a6 HEAD@{2}: reset: moving to f9752a6
    126320d (HEAD -> master) HEAD@{3}: reset: moving to 126320d
    f9752a6 HEAD@{4}: reset: moving to f9752a6
    126320d (HEAD -> master) HEAD@{5}: commit: add bad
    f9752a6 HEAD@{6}: commit: modify good.txt
    9fc37f5 HEAD@{7}: commit (initial): add good.txt
    # 注意这里面的一些版本号是相同的,因为只是通过reset操作前进恢复了一些版本,并没有生成新的文件
    

    使用索引恢复实质上就是移动HEAD指针位置,执行命令

    $ git reset --hard 9fc37f5
    

    HEAD指针就会移动到"9fc37f5"这个版本

    • 使用^~后退版本

    ^只能后退版本,不能向前选择版本,通常使用git reset --hard HEAD^回退到HEAD之前的一个版本,有几个^就表示后退几个版本

    ~也只能后退版本,~n就表示后退n步,在^比较多的时候使用,例如git reset --hard HEAD^^^^^git reset --hard HEAD~5是等价的

    hard/soft/mixed 重置版本的区别

    • soft

    只是在本地库移动下指针,但不会碰工作区和暂存区

    将本地库恢复凸显暂存区的变动了

    • mixed(默认)

    本地库移动下指针,重新设置暂存区,但不重置工作区,所以现在的文件内容会保存

    将本地库和暂存区恢复,就凸显工作区的变化了,reset HEAD可以用来清除暂存区

    • hard

    本地库移动下指针,重置暂存区,重置工作区,所有之后修改的代码都会被丢弃

    正常情况,版本可以使用--hard恢复,但暂存区和工作区文件就恢复不了了

    soft mixed hard
    工作区 working tree 恢复
    暂存区 index 恢复 恢复
    本地库 恢复 恢复 恢复

    diff 比较文件

    git diff,无参数,表示工作区与暂存区比较

    git diff <file>表示指定哪个文件比较

    git diff可以加分支参数,如git diff HEAD表示工作区和当前本地库最新版本比较,git diff HEAD^表示工作区和本地库上一个版本比较

    这里比较下bad.txt文件,7/9/10行表示具体内容,git认为的修改就是删除又新增,因为1后面加了个回车,所以是删除1行,新增2行

    $ git diff bad.txt
    diff --git a/bad.txt b/bad.txt
    index 56a6051..7a754f4 100644
    --- a/bad.txt
    +++ b/bad.txt
    @@ -1 +1,2 @@
    -1
     No newline at end of file
    +1
    +2
     No newline at end of file
    

    Git 分支操作

    branch 创建查看分支

    • 创建分支
    $ git branch [分支名]
    
    • 查看分支
    $ git branch -v
    

    checkout 切换分支

    $ git checkout [分支名]
    

    merge 合并分支

    1. 切换到被合并的分支上
    2. 执行merge命令,例如刚刚创建了一个bak分支,那么就是git merge bak,具体是
      1. git checkout master切换到master分支
      2. git merge bak合并aaa分支的内容

    分支合并冲突

    • 例如创建了一个bak分支,然后bak分支和master分支各修改了相同的一行,然后将master合并到bak,就会出现问题
    Administrator@IGAME MINGW64 /d/GitHub/guigu (bak)
    # 当前是bak分支
    $ git merge master
    Auto-merging good.txt
    CONFLICT (content): Merge conflict in good.txt
    Automatic merge failed; fix conflicts and then commit the result.
    # 自动合并失败,修复冲突,然后手动commit
    Administrator@IGAME MINGW64 /d/GitHub/guigu (bak|MERGING)
    # 当前bak分支,但变成MERGING状态
    

    good.txt内容就变成了

    aaa
    bbb
    <<<<<<< HEAD # 冲突开始
    ccc edit by bak
    ======= # 上面是当前分支的内容,下面是合并来的分支的内容
    ccc edit by master
    >>>>>>> master # 冲突结束
    ddd
    eee edit by bak # 这句话是bak合并的,并未产生冲突解决
    
    • 解决方法就是手动修改good.txt文件,保存

    先用git status查看下当前状态

    $ git status
    On branch bak
    You have unmerged paths.
    # 你有一个未合并的路径
      (fix conflicts and run "git commit")
      (use "git merge --abort" to abort the merge)
    
    Unmerged paths:
    # 未合并路径
      (use "git add <file>..." to mark resolution)
      # 使用"git add <file>..."去标记已解决
            both modified:   good.txt
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    • git add good.txt,再查看状态
    $ git status
    On branch bak
    All conflicts fixed but you are still merging.
    # 所有冲突都解决得了,但你仍然处于merging状态
      (use "git commit" to conclude merge)
      # 使用"git commit"解决merging
    
    Changes to be committed:
            modified:   good.txt
    
    • 然后只需要git commit即可提交,这次不用加文件名

    GitHub

    remote 设置别名

    在GitHub中,仓库的地址是一长串很麻烦,不可能每次都输入这一长串东西,所以git提供了一个别名的功能

    查看所有git的别名:git remote -v

    添加别名

    $ git remote add mf https://github.com/lk722722722/MyFirstRepo.git
    

    添加后会发现有2条记录

    $ git remote -v
    mf      https://github.com/lk722722722/MyFirstRepo.git (fetch)
    mf      https://github.com/lk722722722/MyFirstRepo.git (push)
    

    由于这样设置别名是仓库级的,所以一般都使用origin表示远端位置

    $ git remote rm mf # 删除之前添加的mf别名
    $ git remote add origin https://github.com/lk722722722/MyFirstRepo.git # 设置新别名
    

    push 向远端推送 - 需要凭证

    由于已经设置好了别名,将本地库文件推送到GitHub只需

    $ git push -u origin master
    

    如果创建GitHub仓库的时创建了README.md文件,那本地库推送之前也需要创建此文件,否则将会提示推送失败

    $ git push origin master
    To https://github.com/lk722722722/MyFirstRepo.git
     ! [rejected]        master -> master (fetch first)
    error: failed to push some refs to 'https://github.com/lk722722722/MyFirstRepo.git'
    hint: Updates were rejected because the remote contains work that you do
    hint: not have locally. This is usually caused by another repository pushing
    hint: to the same ref. You may want to first integrate the remote changes
    hint: (e.g., 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    解决方法是先执行一遍合并操作

    $ git pull --rebase origin master
    

    clone 克隆

    很简单,只需要这样即可,在克隆之前也无需init初始化仓库

    $ git clone https://github.com/lk722722722/MyFirstRepo.git
    

    克隆完,不仅把远端的文件下载到本地,还init了本地.git目录,并且创建了origin别名

    远程库的拉取

    pull = fetch + merge

    fetch 远程库拉取

    $ git fetch [远程库地址/远程库地址别名] [远程库分支名]
    

    merge 远程库合并

    $ git merge [远程库地址/远程库地址别名]/[远程库分支名]
    

    注意:merge拉取的时候实际上远端的文件已经下载到了本地

    远端合并思想和本地库合并相同,只是分支名前多了远程库地址/表示和本地不同的另外一个分支

    pull 远程库拉取合并

    实际上是先fetchmerge

    $ git pull [远程库地址/远程库地址别名] [远程库分支名]
    

    两种拉取的选择

    fetch之后文件已经下载到本地,此时已经可以查看文件,只不过没有合并到我们本地工作的仓库中,so:

    • 第一次拉取用clone
    • 之后拉取,文件比较复杂,用fetch+merge
    • 之后拉取,文件较清晰,用pull比较省事

    团队合作中的冲突

    团队合作中肯定会有冲突,当两个人同时修改一个文件, 只有先推送(push)的那个人可以推送到远程库里面,后推送的人只能先拉取(pull)再推送(push)。拉取的时候,修改的位置有自己的内容,也有另一个的内容,这就必须得我们自己去处理冲突(MERGING状态)

    1. 两人分别修改,提交到各自的本地库都没问题(初始化版本A0,HEAD版本A0)
    2. A先执行,git push origin master,没有问题,A把他的版本提交上去了(版本号A,基于parent A0版)
    3. B再执行,git push origin master,就出问题了,此时B的版本不是最新版本(版本号B,基于parent A0版,不是最新HEAD版A)
    4. B需要先 git pull origin master将远端的版本下载下来,此时本地库是MERGING状态
    5. B修改代码,addcommit。现在本地库已经是基于A的版本号新提交的一个版本,再执行git push origin master没有问题(版本号B2,基于parent A/B版)
    6. 如果A还要修改,A也也要pulladdcommitpush,否则因为A的当前版本不是基于最新版本修改的(A本地生成的A2,parent版本是A,不是基于HEAD的版本B2)

    图例,总之push的时候要确保本地的版本是基于远端的HEAD版本做的修改,push才能被接受

    graph BT A0 -- 1 初始版本 --> A A0 -- 2 B的修改晚了一步 --> B A -- 3 B合并HEAD A的内容 --> B2 B -- 3 B也合并自己的内容 --> B2 A -- 4 A又提交了一个版本 --> A2 B2 -. 4 A还需合并HEAD B2的内容 .-> A2 A2 -. 5 以后都是基于HEAD版本编辑 .-> A3

    SSH免密登录

    1. 生成秘钥
    $ ssh-keygen -t rsa -C xxxxxxx@qq.com
    
    1. 之后会生成一个/.ssh目录,下面有id_rsaid_rsa.pub两个文件
    2. id_rsa.pub复制到GitHub的SSH keys处,这样就设置好了,以后就不用输入账号密码了
    3. 这样提交是以ssh协议提交,所以远程仓库的地址变了
    $ git push origin_ssh master
    

    IDE

    git ignore

    IDE会产生很多和IDE版本相关的文件,如果这些文件添加到GIt管理,在团队中每次处理这些文件都将是一件麻烦且毫无意义的是事情,所以需要将这些文件添加到忽略列表中,具体有哪些文件,GitHub列出了一个详细的清单

    <!-- 项目地址 -->
    https://github.com/github/gitignore
    <!-- 与Java相关 -->
    https://github.com/github/gitignore/tree/master/Global
    https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore
    https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
    

    配置方法:

    在仓库目录下新建一个名为.gitignore的文件(因为是点开头,没有文件名,没办法直接在windows目录下直接创建,必须通过右键Git Bash,按照linux的方式来新建.gitignore文件)。 通过将.gitignore文件添加到仓库,其他开发者更新该文件到本地仓库,以共享同一套忽略规则

    在IDEA使用Git(待添加)

    这部分尚硅谷的视频中没有,待之后我添加

    Git 工作流(待补充)

    GitLab(待添加)

    待添加

  • 相关阅读:
    sqlserver 批量删除所有表语句
    C# 中的委托和事件
    Oracle建立用户
    C# Linq获取两个List或数组的差集交集
    Linux下Redis安装与配置操作说明
    word缩印
    centos7上的postgresql10安装和配置
    numpy技巧
    发票二维码扫描增强_06_持续优化
    发票二维码扫描增强_05_构建目标二维码
  • 原文地址:https://www.cnblogs.com/n031/p/11870152.html
Copyright © 2011-2022 走看看