Git命令

### 版本控制工具 

    1.项目模块小组分开开发,每个人开发完后需要整个成一个整体的项目 ,借助版本控制工具来解决 

    2.项目是开发是过程化的,(v1.0 --> v1.1 --> v1.2 --> v2.0)用版本控制工具,轻松切换每一个版本 

### 版本控制工具分类

    git (分布式)

    svn (集中式)

    区别:

        1.不管git 还是svn 都是版本控制工具都能形成版本(version )   

           git能在开发者本机形成自己的版本version控制,但是svn 必须提交中央服务器才能形成版本

        2.不管是git还是svn 如果是要代码合并,必须都要依靠中央服务器

        3.在git中大部分 "合法操作" 都是可以撤回的 ,但是在svn中有些操作是不可以撤回

### 怎么学习git  》》  实验科学

### git 优势

    1.能在本地和服务器形成版本控制

    2.git的版本成重写提交说明

        svn 不可以重写提交说明

    3.git 一般都可以撤回‘后悔’

    4.git 强大的分支系统,每个分支都有独特的函数

            master  --> 主分支  --> 不直接做开发 分支代码稳定,直接上线发布

            dev     --> 开发分支 --> 开发代码的分支 

            test    --> 测试分支  -->  测试人员 测试代码安全性能分支 

        分支:

            版本形成的提交线路 

    5.git形成版本 (全量备份 ) svn (增量备份)

        git: 每个版本保存全部代码文件 (修改的和未修改的)

        svn: 每个版本只保存修改的代码  (修改的代码 项目不完整)

### git 运行在linux 内核上

    1.下载 : git 官网 下载安装包 傻瓜式安装 (下一步 )

    2.检查git 是否安装成功  

        桌面右击 --》 git bash here --> 用git bash 交互窗口打开当前目录 (内部可以写linux命令)

    3. 为了实验 补充常用的linux命令

        cd --> change diretory   --> 切换目录

            cd ~ 切换到用户家目录 

            cd - 切换到上一个目录位置

        ls --> list              --> 列出当前目录下的显示的文件和文件夹 

            -a   查看所有文件包括隐藏文件  linux 中以.开头的文件就是隐藏文件 ./ ../ .abc.txt

            -l   以长格式查看文件和文件夹 

        touch 文件名             --> 创建文件和更新已存在文件的访问时间

        mkdir 文件夹名           --> 创建文件夹

        cat 文件名               --> 查看文件内容

        echo  '  '  >  终端(文件)   --> 输出 字符串

            >  覆盖写 

            >> 追加写

        mv 原文件夹/文件  目标位置/重命名  --> 移动文件、重命名

        cp  文件   位置/文件名            --> 拷贝文件

        cp -r  目录 位置/目录名           --> 拷贝目录 

        pwd  打印当前的工作目录     

        ctrl + a  前置光标

        ctrl + e  后置光标

        ctrl + c  放弃当前行命令状态 开启下一行

        clear  清屏 

        history  查看历史命令 

        vi/vim (linux中自带的编辑器)

            实验: vi修改文件内容

                a) vi 文件名

                    vi打开了一个文件 ,但是不能直接修改,因为vi 存在两种模式 (命令模式 输入模式 )

                b) 默认是命令模式只有切换到输入模式才能修改文件内容

                    按字母 i --》 insert(插入 输入模式) 

                c) 在输入模式的情况下 编辑文件内容

                    修改完文件内容

                d) 推出编辑模式 esc 进入命令模式 

                    :wq!

        rm -rf 文件/文件名       -->

        文件修改 --》 编辑文件内容 

        目录修改 -->  目录重命名 删除 ,目录内部文件的增删改

        window 文件是按照文件后缀名区分文件类型 但是linux 中 他不是以文件后缀名区分文件类型的 (linux中所有的类型都是文件 ,正式因为这样linux系统相对安全)

    4. linux 中的 权限

        d rwxr-xr-x     1 xuanqiyan 197121 0 May 17 08:45 git/

        rwx (所有者) r-x  (所属组) r-x  (其他人)

          r : read  读取

          w : write 写

          x : execute 执行 

  基础实验 // 

#### git 基本实验

    实验一:如何使用git bash 初始化一个本地仓库

        1. 如果是第一次操作git 需要设置email 和 name 

            设置:

                git config --global user.name ""

                git config --global user.email ""

                /*

                    --local   --》 本仓库 --》 .git/config 配置文件中 优先级最高

                    --global  --》 计算机的登录用户 --》 ~/.gitconfig 配置文件中 

                */

            查询:

                git config  user.name  

                git condfig user.email

            删除:

                git config --local --unset user.name

                git config --local --unset user.email

            作用: 是提交代码或者本地形成版本需要根据 name 和 email  识别这个版本作者是谁

        2. 将一个原始的文件夹 变成 git 所能控制的git仓库

            git init

            作用: 在当前目录下形成一个.git这样的隐藏文件夹 还有master分支(默认主分支)的显示

        3.如何形成一个版本?

            touch a.txt

            echo "代码" >> a.txt

            git add a.txt

            git commit -m '版本说明'

                /*

                    [master (root-commit) 24e7b14] 第一次提交

                    1 file changed, 1 insertion(+)

                    create mode 100644 a.txt

                */

        4. 查看提交版本的历史

            git log

                /*

                    commit 24e7b14108f07686817da82a4c50c34b16aee4fd (HEAD -> master)

                    Author: Yanzhijie <1730903@163.com>

                    Date:   Tue May 18 09:07:42 2021 +0800

                        版本说明

                    24e7b14108f07686817da82a4c50c34b16aee4fd  是git 使用sha1 加密算法生成的唯一ID

                    目的:不是为了加密而是为了产生一个不重复的字符串

                */

#### git 中的区域

    3个区域: 工作区 暂存区 对象区

    补充命令:

        git status 查看当前git仓库所有中文件的状态    

    实验二:重新执行实验一 针对每一个次操作查看状态

        touch a.txt

        echo 'aaa' >> a.txt

        git status --》 查看git仓库中的文件状态 

            /*

                On branch master  //在主分支master上

                No commits yet    //还没有任何提交 

                Untracked files:  // untarcked 未追踪 文件:(tracked追踪 )

                (use "git add <file>..." to include in what will be committed) //使用git add 将未追踪的文件 加入到commit之前的区域 (暂存区)

                        a.txt   // 未追踪的文件

            */

        git add a.txt

        git status  

            /*

                On branch master  

                No commits yet

                Changes to be committed: // 暂存区的内容可以被提交 形成版本

                (use "git rm --cached <file>..." to unstage)   //可以使用 git rm --cached <file> 将暂存区的文件重新撤销到工作区

                        new file:   a.txt // 对于暂存区有一个新的追踪的文件a.txt 加入

            */   

        git commit -m '第一次提交' 

        git status

            /*

                On branch master  

                nothing to commit, working tree clean  // 暂存区清空了  工作区 clean 意思是工作区所有的文件都形成版本了,对象区区的最新的版本和工作区的内容完全一致 ,这叫 clean (清空),而不是工作区的文件丢失或者隐藏

            */

    实验三:如何将暂存区的内容重新拉回到工作区

        1. mkdir test && cd test && git init

        2. touch a.txt 

           echo 'aaa' >> a.txt

        3. git add a.txt

        4. git status

            /*

                On branch master

                No commits yet

                Changes to be committed:

                (use "git rm --cached <file>..." to unstage)  //目的: 将暂存区的a.txt 拉回到unstage 状态(工作区)

                        new file:   a.txt

            */

        5. 执行撤销

            git rm --cached a.txt  

            /*    

                注意: 如果第一次从暂存区撤销到工作区 使用这个命令 

                rm 'a.txt' 从暂存区删除了 到工作区了 

            */   

        6. git status

            /*  发现 回到一开始未add之前的状态

                On branch master

                No commits yet

                Untracked files:

                (use "git add <file>..." to include in what will be committed)

                        a.txt

            */

    实验四:提交多个版本 以及日志查看方式

        1. mkdir test && cd test && git init

        2. touch a.txt b.txt

            echo 'aaaa' >> a.txt

            echo 'bbbb' >> b.txt

        3. git add .  // 注意: 这个 "." 指的是 相对于上一次提交的本版而言工作新所有更改(新增 删除 修改)的文件 

        4. git commit  

           注意:如果commit时候没有 加-m 参数 会打开vi编辑器 让你输入版本说明文字  ,说明文字可以多行输入

        5. 第一个版本形成了 

            git log 查看提交日志 

        6. touch c.txt

           echo 'cccc' >> c.txt

        7. git add .

        8. git status

            /*  

                On branch master

                Changes to be committed:

                (use "git restore --staged <file>..." to unstage)  

                        new file:   c.txt

            */ 

        9. git restore --staged c.txt

            /*

                注意: 对比实验三 都是从暂存区撤销到工作区,但是命令不一样,因为此时第二次加入到工作区了,以后每一次撤销都是用这个命令 

            */

        10. git commit -m 'xxx'

            /*

                不能直接提交,因为暂存区没有任何何以提交的内容

            */ 

        11. git add .

        12. git commit -m '第二个版本'

        13. git log   --》 查看所有日志

            /*

                commit cb98a0d2743b70f49b9c1606fc999ec3f2c1a477 (HEAD -> master)

                Author: Yanzhijie <1730903@163.com>

                Date:   Tue May 18 10:34:33 2021 +0800

                    第二个版本

                commit f851d27133b2e057db3e6eefbb3d256bdeceafaa

                Author: Yanzhijie <1730903@163.com>

                Date:   Tue May 18 10:19:27 2021 +0800

                    这是第一次提交

                    这个代码很棒

                    这是我写的

            */

        14 多种方式查看日志

           git log -n   --> 查看最近几次提交日志 

           git log --pretty=oneline --> 以单行查看日志内容

           git log --pretty=format:"%h - %an ,%ar : %s"

           /*

           "%h      - %an       ,%ar            : %s"

            cb98a0d - Yanzhijie ,16 minutes ago : 第二个版本

           */

  检出实验 // 

    检出:

        对于一个文件修改(modify) 或者是 删除(delete) 那么文件名之前就会有对应的操作动作

            modified : a.txt

            delete : a.txt

        检出指的是移除前面的动作 恢复到动作之前的文件状态

   ### 实验五 对已提交的文件再次执行编辑 

       mkdir test && cd test && git init

       touch a.txt b.txt

       echo 'aaaaa' >> a.txt

       echo 'bbbbb' >> b.txt

       git add .

       git commit -m '第一个版本' 

       vi a.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)

                    modified:   a.txt

            no changes added to commit (use "git add" and/or "git commit -a")

            1. 由于 git add <file>... 说明 被修改的文件重新拉回到工作区 

            2. 可以使用  git restore <file>... 撤销此次的修改 ---> 检出 

            3. 如果确定修改 要对这次修改做版本提交 使用 git add . / git commit -m 

        */

        git restore a.txt  //检出操作 移除a.txt的前面的修改动作恢复修改之前的文件状态

        git status

        /*

            On branch master

            nothing to commit, working tree clean

        */

        vi a.txt  --> 编辑内容 

        git status

        git add . / git commit -m ''  //对修改的内容做版本提交

    ### 对已提交的文件再次执行删除 

        删除模式:基于操作系统的文件删除 rm  / git方式的删除 git rm 

        场景:有两个commit  ,第一个commit 包含a.txt 和 b.txt 第二个commit 包含a.txt b.txt 只不过对a.txt重新修改了 

              删除b.txt

        实验六 执行操作系统删除

            ls --> a.txt 和 b.txt

            rm -rf b.txt --> 操作系统的直接删除 

            ls --> 只有a.txt

            git status

            /*

                On branch master

                Changes not staged for commit:

                (use "git add/rm <file>..." to update what will be committed)

                (use "git restore <file>..." to discard changes in working directory)

                        deleted:    b.txt

                no changes added to commit (use "git add" and/or "git commit -a")

                1. git add file 说明此时删除的b.txt 文件拉回到工作区 ,只不过看不到b.txt

                2. 执行了git add  /git commit  形成新的版本 ,这个版中才真实的没有b.txt

                3. 也可以使用 git restore <file>... 对删除动作进行检出

            */  

            git restore b.txt // 检出删除

            ls --> 发现b.txt 

            rm -rf b.txt --> 再次执行删除 

            git add .

            git status

            /*

                On branch master

                Changes to be committed:

                (use "git restore --staged <file>..." to unstage)

                        deleted:    b.txt

  

                注意:1. add 提交的不是某一个单独的文件 二十对某一个文件的删除动作 ,如果后面执行commit 也是提交的文件的删除动作 ,

                形成的新版本中就真的不存在b.txt文件了 

                     2. 如果现在还想后悔  

                        a) git restore --staged <file>... 将暂存区的提交撤销到工作区 

                        b)  git resrore <file>    检出了删除动作 工作区就clean这个状态了 b.txt的文件就回来了


 

            */

            git commit -m '删除了b.txt 文件'

            

            ls --> 只有a.txt 

            git status  --> 工作区也是干净的

            问题: 此时b.txt文件在工作区消失了 还能否重新拉回b.txt文件 ?

                  可以 需要切换版本就可以实现   

            

        实验七 执行git方式的删除  

            git rm a.txt

            ls --> a.txt删除了 

            git status

            /*

                On branch master

                Changes to be committed:

                (use "git restore --staged <file>..." to unstage)

                        deleted:    a.txt

                注意:

                    如果是git rm 删除一个已提交的文件 ,这个文件包括动作(deleted)拉回到暂存区

            */

            //如果要撤销删除

            git restore --staged a.txt --> 将暂存区的a.txt 拉回到工作区 

            git restore a.txt --> 执行检出 

            ls  --> 出现a.txt

            git status  --> 工作区 干净

            //如果要提交删除 

            git rm a.txt

            git commit -m '删除a.txt' // 为什么不用add ? 因为已经在暂存区,所以直接提交删除

 /// git 忽略 /

    .gitignore : 作用是git在做提交的时候忽略的文件

    1.创建.gitignore

    2.编辑.gitignore文件

        # 忽略单个文件

        a.txt 

        # 忽略一类文件 

        *.txt

        # 忽略某一类文件 除了特定文件 

        *.js 

        !c.js

        #git会自动忽略空目录

        #忽略一个非空的目录

        /a

        #忽略目录下的某些文件名 

        /a/*

        /a/*/*.txt  -->  /a/o/*.txt  /a/b/*.txt

        /a/**/*.txt --> /a/o/*.txt  /a/o/c/d/*.txt

  /// git 分支实验 branch /       

    

    分支的概念:分支是由多个commit 按照一定的时间顺序链成的工作提交线, 分支名指向最新提交的commit 

    分支分类:

        master 主分支   代码发布分支 不直接做开发 

        dev    开发分支  代码开发分支

        test   测试分支   

        hot    bug热修复分支

    实验八: 分支的创建 切换 删除 查看  

        注意: 在没有任何 commit 的情况下 不能创建新的其他分支

        //创建分支

        git branch  分支名 

        //查看分支

        git branch  

            -v 查看分支的同时查看分支所指向的commit 

        //切换分支 

        git checkout 分支名  

        //创建并切换分支

        git checkout -d  分支名 

        //删除分支

        git branch -d    分支名 


 

    实验九:不能删除分支的实验(1)

        1.在当前分支不能删除自身

        2.如何分支包含‘未合并’的内容不能删除分支 

            未合并:这个分支的commit版本只有该分支指向与它,如果删除这个分支,这个commit 就无法再次获取,这么commit 就是‘未合并’的   

        git init

        touch a

        echo 'aaa' >> a

        git add .

        git commit -m 'init'

        //创建新分支

        git checkout  -b dev

        

        git branch -av

        /*

          * dev    abd2701 init  

            master abd2701 init 

        */

        //dev 分支做提交

        touch b && echo 'bbb' >> b

        git add .

        git commit -m 'dev第一次'

        git branch -v

        /*

            * dev    dsad123 dev第一次

            master   abd2701 init 

        */

        git checkout master 尝试删除dev 

        git branch -d dev

        /*

            error: The branch 'dev' is not fully merged.

            If you are sure you want to delete it, run 'git branch -D dev'.

            分支dev 有一个未合并的commit ,如果删除 这个commit 就无法再次还原(找到 ),不建议删除

            如果想删除 使用 D 强制删除

        */

        思路1: 既然未合并的commit 只有唯一的一个分支指向与它从而导致不能正常删除,那么可以基于这个commit 做另一个分支来指向与它 ,对于这个commit来说就不是‘未合并’的

        git checkout  dev

        git checkout -b test

        git branch -v

        /*

            dev      dsad123 dev第一次  因为有两个分支指向与commit 所以dev分支可以删除的

        *   test     dsad123 dev第一次

            master   abd2701 init 

        */

        git checkout master

        git branch -d dev  --> ok 

        思路2:强制删除 

        git branch -D test

     实验九:不能删除分支的实验(2)

        git branch -v

            dev    0ea7331 dev第一次

            * master abd2701 init

        git branch -d dev

        /*

            error: The branch 'dev' is not fully merged. //dev上有未合并的版本,所以要删除 必须合并

            If you are sure you want to delete it, run 'git branch -D dev'.

            合并:指的是其他分支(matser)指针只想于当前的commit ,这个指针移动的过程叫做合并 

        */   

        // 合并位置master 合并dev

        git merge dev

        /* 

            Updating abd2701..0ea7331 // master的指针移动

            Fast-forward

            b | 1 +

            1 file changed, 1 insertion(+)

            create mode 100644 b

        */   

        git branch -v

        /*

              dev    0ea7331 dev第一次

            * master 0ea7331 dev第一次

        */ 

        //再次尝试删除dev

        git branch -d dev --> ok 

    实验10 :补充实验

        两个细节:

            1.如果在dev分支上进行了写操作(新建/删除/修改),这个写操作仅在工作区 和 暂存区(没有形成版本)

              master 分支是能看到这个写操作的 ,如果将写个写操作提交,master分支是看不到这个写操作

            结论: 分支之间是共享工作区和暂存区的

            2.如果在dev分支上进行了写操作(新建/删除/修改),这个写操作仅在工作区 和 暂存区(没有形成版本)。

             此时dev分支是可以删除的

    实验11: 分支合并方式 (ff 默认 / no-ff)

        场景:master 分支相对于dev落后两个commit ,使用meger默认合并

        gir branch -v

        /*

            * dev    830ef05 dev第四次提交

              master e07ebf0 dev第二次 c文件

        */   

        //master分支合并dev分支 

        git merge dev   

        /*

            Updating e07ebf0..830ef05

            Fast-forward  //前进 ff

            ff合并的细节:

                1.  两个分支归于从同一个commit

                2.  fast-forward 会丢失分支信息 

                    git log --graph

        */ 

        场景:master 分支相对于dev落后两个commit ,使用meger默认合并

        git branch -v

        /*

            * dev    297cbf0 新建b.txt

             master 830ef05 dev第四次提交

        */

        git checkout master

        git merge --no-ff dev 

        /*

            1.使用--no-ff合并主动合并的分支会指向下一个新的commit版本

            2.--no-ff 不会丢失分支信息 

                git log --graph --pretty=oneline --abbrev-commit

        */

        //打开编辑器要求输入版本说明文字 --》 有新的commit形成

        git branch -v

        /*

              dev    297cbf0 新建b.txt

            * master 0ad5dc9 Merge branch 'dev' no-ff 合并dev分支

        */

        git checkout dev

        git merge mster  --> 两个指向同一个commit

    实验12: 在和并分支的时候的冲突   (非常重要)

        场景:每个分支对同一个文件 的同一行有不同的实现 ,前提是分支指向的版本之间没有时间关系

        mkdir test && cd test && git init

        touch a 

        git add . && git commit -m 'init'

        //dev分支对a文件的修改

        git checkout -b dev

        echo 'dev...' >> a

        git add . && git commit -m 'dev...'

        //master分支对a文件的修改 

        git checkout master

        echo 'master...' >> a 

        git add . && git commit -m 'master...'

        //在master 合并 dev 分支

        git merge dev

        /*

            Auto-merging a  //自动合并a

            CONFLICT (content): Merge conflict in a // 内容冲突

            Automatic merge failed; fix conflicts and then commit the result. // 解决冲突 ,并且提交结果

        */

        // 如何解决冲突??

                1.查看冲突文件,并通过协商解决该冲突

                cat a 

                /*

                    <<<<<<< HEAD  (HEAD 指向当前分支master->)

                    master...

                    =======

                    dev....

                    >>>>>>> dev

                    master...,dev... //最终达成一致的解决方案,以这行代码为准

                */

                git status

                /*

                    On branch master

                    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) // 提交最终修改的a文件

                            both modified:   a

                    no changes added to commit (use "git add" and/or "git commit -a")

                */

                2. git add . // 提交修改a文件 

                git status

                /*

                    On branch master

                    All conflicts fixed but you are still merging.

                    (use "git commit" to conclude merge)

                    Changes to be committed:

                            modified:   a

                */

                3. git commit -m  '合并dev分支,解决冲突a文件'

        // master分支指向最新的版本(冲突解决的版本 ),但是dev分支 还是指向之前的版本。需要将dev的分支移动也指向最新的版本,(?? 会不会冲突呢?不会!)

        cat a 

        /*

            master...,dev...

        */

        

        //切换到dev

        git checkout dev

        cat a

        /*

            dev...

        */

        git merge master 

        cat a

        /*

            master...,dev...

        */

        git branch -v

        /*

            * dev    f90becf 合并dev,解决冲突文件a

              master f90becf 合并dev,解决冲突文件a

        */

    实验13: 两个分支不同文件合并会不会产生冲突? (不会)

        场景:每个分支对不同文件有不同的实现 ,前提是分支指向的版本之间没有时间关系

        

        //dev分支对新建c文件

        git checkout -b dev

        touch c && echo 'cccc' >> c

        git add . && git commit -m 'dev...'

        //master分支新建b文件

        git checkout master

        touch b && echo 'cccc' >> b

        git add . && git commit -m 'master...'

        //在master 合并 dev 分支

        git merge dev

        /*  不会产生冲突 因为不同文件

            会打开vi编辑器 要求输入版本说明,证明有一个新的版本生成(同时保留master 的 b文件和dev的c文件)

            master指向最新的commit ,但是dev还是之前的commit 

            所以需要 dev 指向最新的commit 

        */

        //dev合并最新的commit 

        git checkout dev

        git merge master 

        git branch -v

        /*

            * dev    32854c1 Merge branch 'dev'......

              master 32854c1 Merge branch 'dev'......

        */

    实验14:  两个分支同一文件不同行有不同实现,合并会不会产生冲突 (也会产生冲突)

    实验15:  两个分支同一文件完全一致,合并会不会产生冲突 (不会产生冲突)

    总结:

        1.冲突的怎么产生的?

            前提:两个版本之间没有时间顺序

            merge 合并的时候计算机会尝试自动合并,但是在遇到同一个文件的时候,不知到怎么合并,所以提示冲突

            需要人为介入来解决冲突

        2. 两个没有时间关系的分支合并 ,一定会产生新的提交版本(冲突后的版本,未冲突的版本),

           被合并的版本会移动到主动发起合并的分支上

/git 版本前进和后退///

    版本前进

        git reset --hard HEAD^ 撤销到上一个版本

        git reset --hard HEAD^^ 撤销到前两个版本

        git reset --hard HEAD~n 撤销到前n版本

        HEAD --》 分支 --》 最新的commit sha1

    版本后退 

        git reset --hard 版本(sha1)

        需要借助良好的注释说明

        git reflog --》 查看所有的操作记录 


 

/游离操作///

    checkout

        1. git checkout 分支 --》切换分支

        2. git checkout -b 分支 --》 创建并切换

        3. git checkout -- 文件名  --》检出文件 

            补充:git checkout -- 文件名 检出实验

        4. git checkout sha1   

            /*

                You are in 'detached HEAD' state. You can look around, make experimental

                changes and commit them, and you can discard any commits you make in this

                state without impacting any branches by switching back to a branch.

                If you want to create a new branch to retain commits you create, you may

                do so (now or later) by using -c with the switch command. Example:

                git switch -c <new-branch-name>

                Or undo this operation with:

                git switch -

                Turn off this advice by setting config variable advice.detachedHead to false

                HEAD is now at abc9b1a version 4

                1.你处于独立的状态(游离状态)

                2.可以执行写写操作,但是写操作必须提交  (commit-- 新的sha1)

                3.入提交了写操作,必须起一个新的分支指向于这个sha1

                4.在游离状态下未作任何操作 可以使用git checkout master  切出游离状态

            */

         在游离状态下做了版本提交 

         git add .

         git commit -m ''  --> sha1

         git branch 新分支名 sha1   

 // 保存现场 还原现场 ///

    规范:

        1.建议(可以不遵守):一个功能在没有开发完全的情况下不要commit 

        2.规范(必须遵守):如果两个分支之间处于不同的commit 阶段,当前分支在没有commit 的情况下不能直接切换到其他分支

    实验 16: 不可以切分支的情况 

        mkdir test && cd test && git init

        touch a 

        git add . 

        git commit -m 'init'

        //创建新分支

        git checkout -b dev 

        //在dev上做操作

        echo  'dev ...' >> a   //能切分支 

        git  add .             //能切分支

        git commit -m 'dev ...'//能切分支 

        echo 'dev xxx' >> a    //不能切

        /*

        //如果切过去 a文件的内容将丢失

        error: Your local changes to the following files would be overwritten by checkout:

                a

        //想切分支 1.提交 2.保存现场        

        Please commit your changes or stash them before you switch branches.Aborting

        */

        //保存现场

        git stash

        //查看保存的现场

        git statsh list

        /*

            stash@{0}: WIP on dev: a581bd6 dev version 1

        */         

        //还原现场

        git stash  apply / pop 

        /*

            apply :还原现场

            pop :  还原现场,还能将保存的该现场删除

        */


 

        //删除现场

        git stash drop stash@{2} 

        /*

            不能连续还原两个现场

        */

   实验17:还原现场冲突

        场景:基于一个commit 

        vi a  --> 第二行 xxx

        //保存现场

        git stash   

        vi a --> 第二行 ooo

        git add .

        git commit -m '第二行ooo'

        //还原现场

        git stash apply 

        /*

            Auto-merging a

            CONFLICT (content): Merge conflict in a

            冲突: 现场的第二行和版本中a文件的第二行冲突

        */

        //解决冲突

        vi a  --》 修改冲突的行

        git add .

        git commit -m '解决冲突'

/// git 追责 


 

    git blame 文件名  --》 看这个文件的每一行代码都是谁写的 

    /*

        59e92fc2 (Yanzhijie 2021-05-25 10:44:42 +0800 1) 111

        65881bbf (Yanzhijie 2021-05-25 10:45:11 +0800 2) 222

        dcf6d44f (Yanzhijie 2021-05-25 10:45:22 +0800 3) 333

    */

  github //

    1. 创建github账号

        name

        email(必须真实的,发邮:重置密码 长时间不登陆的话需要发送登录验证码)

    2.实验18:创建一个github公共仓库(public 共有 private 私有 )

        两种选择:

            1.勾选readme

            2.不勾选readme

    推送协议:

         /*

            https: 以这种方式推送服务器

                定期推送需要让输入账号和密码 

            ssh :非对称密钥对 (私钥:本地  、公钥:用户、github仓库)建议

                本地私钥   ---》 gihub仓库的公钥

                本地私钥   ---》 gihub用户公钥(多个 )

            配置私钥和公钥

            1.本地 执行 ssh-keygen -t rsa 生成公钥私钥

                用户家目录下生成    

                    .ssh/

                        id_rsa  --> 私钥

                        id_rsa.pub --> 公钥

            2.将公钥配置到github 用户下,以后本地和github账户下的人一个仓库都可以免密钥登录            

        */        


 

    3.不勾选readme创建仓库,本地链接远程仓库

    //ssh

        echo "# test1" >> README.md

        git init

        git add README.md

        git commit -m "first commit"

        git branch -M master

        git remote add origin git@github.com:XuanqiYan/test1.git

        git push -u origin master:master

        //推送失败 原因没有配置ssh 密钥

        //配置密钥

        git push -u origin master:master

        /*

            -u : 将本地的master 和远程 master 建立关联 并缓存

        */    

        touch b  && echo 'bbb' >> b

        git add . && git commit -m '新建b'

        git push --》 ok 

    4. 勾选readme.md 使用ssh

        注意:服务器已经形成了一个带版本的git仓库,不需要在本地 执行 git init 等操作,只需要将

              这个仓库克隆下来就可以

        git clone  git@github.com:XuanqiYan/demo.git  

        cd demo

        touch a  && echo 'aaaa' >> a 

        git add .

        git commit -m '新建a'

        git push // ?? 用什么协议 ssh  


 

        git remote  show --》 查看本地有几个远程仓库

        /*

            origin : 一个远程库

        */

        git remote show origin  --》 查看origin 远程库的具体信息

        git  branch -av 

        /*

            $ git branch -av

                * master                b41e9fb xinjian a

                remotes/origin/HEAD   -> origin/master  追踪分支

                remotes/origin/master b41e9fb xinjian a 追踪分支

            本地分支 --  追踪分支  -- 远程分支

        */ 

        注意:

         如果本地分支master 和远程分支master 交互后,会在本地产生追踪分支 remotes/origin/master

         这个分支是可以切过去的,处于一种游离状态

         追踪分支的作用:

            本地和远程交互都需要通过这个追踪分支

            push 推送

                本地master -->  remotes/origin/master --> 远程master

            pull 拉取

                远程master -->   remotes/origin/master --> 本地master

    实验19 :了解追踪分支

        场景: 建立新的远程库(勾选readme),本地clone 远程库

        git branch -av

        /*    

            * master                4ee520a Initial commit

              remotes/origin/HEAD   -> origin/master

              remotes/origin/master 4ee520a Initial commit

            结论:master 主分支 和 master的追踪分支同时指向同一个commit 

        */ 

        //master 做一次提交

        touch a && echo 'aaa' >> a

        git add . && git commit -m 'version 1 '

        git status

        /*

            On branch master

            Your branch is ahead of 'origin/master' by 1 commit. //master 分支 领先追踪分支以一个commit 

            (use "git push" to publish your local commits)

            nothing to commit, working tree clean

        */  

        git branch -av

        /*

            master                438da12 [ahead 1] version 1 新建 a文件

            remotes/origin/HEAD   -> origin/master

            remotes/origin/master 4ee520a Initial commit

        */

        //master 再次做提交  发现master 比 追踪分支 领先2个commit 

        //做push 推送 

        git push --》 将本地master 两个版本 提交到远程仓库了 

    实验20: 拉去 git pull

        场景: github官网直接在远程 仓库的master分支上做了一个新的 commit

              远程master 领先本地master 一个commit 

            如何知道远程分支领先本地分支

            git remote show origin 

            /*

                 (local out of date) 本地落后

            */

            //执行拉取

            git pull 

            /*

                git pull   = git fetch (拉取) + git merge (合并)

            */

        场景: github官网直接在远程 仓库的master分支上再做了一个新的 commit      

            git fetch

            /*

                From github.com:XuanqiYan/abc

                b054bd5..e1f4d2e  master     -> origin/master 远程master 到 本地 追踪分支 

            */

            git branch -av

            /*

                *   master                b054bd5 [behind 1] c  // 落后一个版本

                    remotes/origin/HEAD   -> origin/master

                    remotes/origin/master e1f4d2e 新建的xxx.txt

            */

            git  merge  // 注意:后面没有分支名 代表默认合并的是其追踪分支 

    实验21:模拟多人推送代码(解决冲突)

        场景:模拟多用户

            远程新建仓库 克隆到本地的两个文件夹(第二个需要重命名)

            分别进去两个本地仓库 做用户区分

            git config --local user.name ''

            git config --local user.email ''

            test  --> lisi

            test1 --> zhangsan

        步骤:

            lisi操作:lisi 提交并执行push 推送 

                touch a  && echo 'lisi....'  >> a

                git add . && git commit -m 'lisi a文件'

                git  push 

            zhangsan操作:

                touch a  && echo 'lisi....'  >> a

                git add . && git commit -m 'zhangsan a文件'

                git push  --> 报错

                /*

                    报错原因:在执行git push 之前 必须拉取 git pull

                    总结: 多人使用仓库 每个人在执行推送之前都要事先拉去 别人的代码 到本地 

                */

                //执行git  pull   == fecth + merge

                git branch -av

                /*

                    *   master                a115bfd [ahead 1] zhangsan 的 a 文件

                        remotes/origin/HEAD   -> origin/master

                        remotes/origin/master f803d1e Initial commit

    

                */

                git fectch 

                git branch -av

                /*

                    master                a115bfd [ahead 1, behind 1] zhangsan 的 a 文件

                    remotes/origin/HEAD   -> origin/master

                    remotes/origin/master cf0a82c lisi 的a文件

                */

                git merge  

                /*

                    自动合并产生冲突 

                */

                解决冲突

                vi  && git add . && git commit

                //张三继续推送

                git push  (实际推送的是两个commit)

        

        lisi 操作:(拉取master上最新的两个commit 并合并)

            git fetch 

            git branch -av

            /*

                *  master                cf0a82c [behind 2] lisi 的a文件

                    remotes/origin/HEAD   -> origin/master

                    remotes/origin/master f5a4b40 解决冲突

            */

            git merge //不会产生冲突(因为 fast-forward)

    实验22:本地新建dev分支 但是远程没有dev分支 完成推送 

        场景:基于上面实验21场景

        用户lisi 操作:

            git checkout -b dev

            echo 'lisi dev分支操作' >> dev_a.txt

            git add . && git commiy -m 'lisi dev分支的 version 1'

            git branch -av

            /*

                *  dev                   02dd50a lisi dev version 1

                    master                47130ce 合并lisi的 b 文件

                    remotes/origin/HEAD   -> origin/master

                    remotes/origin/master 47130ce 合并lisi的 b 文件

                注意: 并没有 remotes/origin/dev 这样的追踪分支,因为没有交互不会产生

            */ 

            //将本地dev分支推送到远程(没有dev)

            git push  --》》 第一次 no  

            /*

                fatal: The current branch dev has no upstream branch.

                To push the current branch and set the remote as upstream, use

                git push --set-upstream origin dev

            */  

            git push -u origin dev:dev  --> 第二次 ok

            /*

                远程仓库 出现dev 分支了 

                还出现  dev had recent pushes less than a minute ago  (compare 可以将远程的master 和 新的dev 进行合格的提示 )    

            */  

            // 本地dev在形成版本

            echo 'lisi dev分支操作' >> dev_b.txt

            git add . && git commiy -m 'lisi dev分支的 version 2' 

            git push  --》 ok 

            git branch -av

            /*

                *   dev                   02dd50a lisi dev version 1

                    master                47130ce 合并lisi的 b 文件

                    remotes/origin/HEAD   -> origin/master

                    remotes/origin/master 47130ce 合并lisi的 b 文件

                    remotes/origin/dev    02dd50a lisi dev version 1

                    //新出现的dev的追踪分支 

            */

    实验23:远程dev分支但是本地没有dev分支,拉取dev到本地

        场景:接实验22

        //拷贝zhangsan的库

        cp -r ./test1 ./test2

        cd test1

        //处于 master 分支 本地并没有 dev和 dev的追钟分支

        git fetch 

        git branch -av

        /*

           * master                47130ce 合并lisi的 b 文件

            remotes/origin/HEAD   -> origin/master

            remotes/origin/dev    ef41d2a lisi dev version 2 //新出现的追踪分支

            remotes/origin/master 47130ce 合并lisi的 b 文件  

            fetch作用:

                1. master 执行的fetch  会把master的最新的commit 拉取下来 ,但是master没有新的commit 

                2. fetch 也会对比远程仓库的追踪分支,将没有的追钟分支拉到本地 并且关联

                3. 本地存在 /origin/dev 但是还没有 dev分支 

        */

        //建立dev 分支

        git checkout -b dev 

        git branch -av

        /*

            *   dev                   47130ce 合并lisi的 b 文件  

               // 并没有 ahead behind 2  证明:dev分支和 orgin/dev 并没有任何关联关系 

                master                47130ce 合并lisi的 b 文件

                remotes/origin/HEAD   -> origin/master

                remotes/origin/dev    ef41d2a lisi dev version 2

                remotes/origin/master 47130ce 合并lisi的 b 文件

        */
 

        //重新建立 dev 并和 origin/dev 建立追踪关系

        git checkout -b dev --track origin/dev

        git checkout -b dev  origin/dev
 

/ git 变基 /

    git merge 被合并分支

    git rebase 被变基分支 (灵活)

    实验24: 变基操作

        场景: 

            版本                                    分支   

            init   1                              -->master

              | --> version test    2             --> test

              | --> a.txt 3 --> b.txt 4--> c.txt 6  --> dev  

            //在test 分支合并 dev分支

            git checkout test

            //merge 合并

            git merge dev  //时间顺序 有可能在看日志的时候不一定符合逻辑顺序

            git log  

            /*

                54f3211 - Yanzhijie ,53 seconds ago : test分支 使用 merge 方式合并 dev 分支

                7f94cf2 - Yanzhijie ,2 minutes ago : c.txt

                cae4e98 - Yanzhijie ,2 minutes ago : b.txt

                85ddd43 - Yanzhijie ,3 minutes ago : a.txt

                2f1fa2f - Yanzhijie ,3 minutes ago : version test

                35475d7 - Yanzhijie ,5 minutes ago : init

            */

            // test 变基合并 dev

            git rebase 分支 // 逻辑顺序 

            /*

                Successfully rebased and updated refs/heads/test.

                merge : 时间顺序 还会产生新的commit 

                rebase : 逻辑顺序 不会产生新的commit 

                注意:

                    1.从代码层面来说这两种方式没有什么区别

                    2.merge 合并会有新的commit  但是 rebase 不会,merge 合并完对日志查看不太友好

                    3.日志的顺序决定了 版本撤销和前进的顺序

            */

            git log

            /*

                a0297d6 - Yanzhijie ,3 minutes ago : test.txt

                a7fc178 - Yanzhijie ,3 minutes ago : c.txt

                1aca675 - Yanzhijie ,3 minutes ago : b.txt

                d43b86b - Yanzhijie ,3 minutes ago : a.txt

                c9c7ea5 - Yanzhijie ,4 minutes ago : init

            */

    实验25:变基合并冲突 和解决冲突

        场景:

        //master 分支 变基合并dev

        git rebase dev

        /*

            Could not apply 687e70b... master 1

            CONFLICT (add/add): Merge conflict in a.txt

            Auto-merging a.txt

        */    

        //解决冲突 

        vi 冲突文件 解决冲突

        git add .

        git rebase --continue  //rebase 会产生新的版本

        git rebase --abort // 可以在变基的过程中任何一个时间点执行这个命令来放弃变基,回到变基之前的状态

     实验25:变基合并冲突 和放弃解决冲突

        场景:

            init 

              |  --> a.txt  --> mster 分支 第一行'master ...'

              |  --> a.txt  --> dev 分支 第一行'dev...'

           // mster分支变基合并dev

           git rebase dev

           //放弃变基

            git rebase --abort 

           vi 冲突文件

           //放弃变基

            git rebase --abort 

    实验26: 多次commit 合并成一个commit 

        git log

        /*

            458138d - Yanzhijie ,6 seconds ago : init

            14d88b6 - Yanzhijie ,34 seconds ago : init

            6cab2b6 - Yanzhijie ,72 seconds ago : init

        */

        git rebase -i HEAD~2

        /*

            s : 合并到下一个

            d : 删除

        */

  git父子仓库  ///

    项目背景:父库A 需要引用 子库B (B中的代码是A的一个模块或者是文件夹)

    准备:

        创建了两个独立的远程仓库A和B

        注意:

            如果在同一个github账号下,不需要配置新的ssh协议 

            如果不在同一个github账号下,本地电脑需要和另一个ssh配置协议

    实验27操作:

        //将A库拉到本地

        git clone git@github.com:XuanqiYan/A.git

        //本地A库中添加远程B库 

        git submodule add  ssh地址

        /*

            1. 将远程的B库下载到本地的当前的文件夹中 

            2. 生成一个配置文件 .gitmoudules 

                [submodule "B"]

                    path = B

                    url = git@github.com:XuanqiYan/B.git

            3. 只是在本地A/B建立了父子关系 ,但是远程A/B是相互独立的 

        */

        //如何让远程的A库知道B库是子库

        git add  .

        git commit -m 'A/B建立关系'

        git push 

        //如果B库有跟新,那么对于父仓库是否可以感知到跟新?

        远程仓库A 不会主动感知远程B的跟新

        本地仓库A 不会主动感知远程B的跟新

        //如果让本地A拉取远程B的最新内容

        cd A/B

        git pull   

        //如何让远程A库更新远程B的内容

        cd A/

        git add .

        git commit -m '更新B'

        git push 

    实验28:面对多个子库怎么批量更新

        cd A/

        git submodule foreach git pull  //遍历每一个子库 然后执行拉取子库最新内容

        //如何克隆一个带有子仓库的远程库

        git clone ssh地址  --recursive  

        //删除B库

        git rm --cache B

        rm -rf B 

        rm -rf .gitmodules

        git add .

        git commit -m '删除B'

        git push 

    裸库

        git init --bare 

    /// github 码云 gitlub  (服务器自己搭建)

  gitflow 工作流  ///

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值