git操作详述

本讲解以git命令操作为主来说明各种操作,配合截图,最后再了解这些命令在eclipse中应该点击哪里实现该操作。本次git操作以gitlab.succez.com为远程仓库地址。

初学者应该以学习git命令提示行语句为重,不要去学习可视化的点击操作,比如IDE自身提供的可视化git操作。

前言

1.git使用中有四个区域要分清楚,即

  • Workspace:工作区
  • Index/Stage:暂存区
  • Repository:仓库区(本地仓库)
  • Remote:远程仓库

      以上四个区域等到了合适的讲解地方将作介绍,结合例子讲解,直接说名称词义是解释不清楚的。

2.在windows上安装git

    在https://git-scm.com/download/win页面下载git并安装,如图:

安装过程直接点击默认即可,打开git安装路径,点击git-bash.exe运行(也可以点击桌面快捷启动图标,如果有的话),如图:

注:git bash和git cmd 操作风格略不同,前者是linux风格,后者是windows风格,推荐git bash。

正文

一、本地仓库

安装后打开,需要配置用户名和邮箱作为标识,命令如下:

打开资源管理器,在windows我的电脑下D盘,新建一个文件夹,命名为testgit,如图:

然后在启动git-bash.exe后的页面中输入以下命令如图:

上图命令中有两条语句,如下:

 cd  /d/testgit         用来进入到目标文件夹

 git  init                  用来将本文件夹创建作为一个版本库,即将这个目录变成一个git可以管理的仓库

此时你会发现如上图,路径上有"(master)",表示在将该文件夹变成一个git可以管理的仓库的同时,也新建了一个master分支(先不要考虑分支是什么概念,先简单理解为版本库的一个副本,一个仓库新建的时候就有一个默认的主副本master)。

再次截图该文件夹,如图:

       这时发现该文件夹下,有一个.git子文件夹,这个文件夹目录用来跟踪管理版本的,以后这个本地仓库testgit所有的跟踪记录都将放在.git里面(.git里面有文件专门存放一些记录和参数),只要该文件夹testgit下的文件有任何改动,都将有所记录。

       值得注意的是,git管理的文件变化是指txt文本文件,xml文本文件,即一切文本文件,和源代码文件,比如js文件,java源代码,网页文件,php文件,c,c++等等,这些文件发生变化,git都会记录具体的变化位置和变化的内容;但对于二进制文件,比如图片文件,视频文件,git只能知道文件的大小发生了变化,但无法通知其变化的位置。

       下面进行一些示例操作:

        1.我在文件资源管理器的当前文件夹下新建一个文本文件README.md,内容为:1111111,保存,如图:

           

            使用git status来查看该文件夹(即工作区,应该说是master分支下该工作区)的变化:

             

             表示该新建的文件并没有被添加到暂存区也没有提交到本地仓库。

              接着使用git add  文件名   来添加该文件的变化到暂存区:

              

               输入命令后没有任何提示,表示添加到暂存区成功(可以试试,当一个文件没有被修改,然后添加到暂存区,控制台会返回什么文件提示,或者一个文件被修改一次,然后被添加到暂存区一次,接着反复使用添加到暂存区命令),

               接着再查看该文件夹的状态,如图:

               

               表明文件README.md的修改被添加到了暂存区,但是还没有提交。                     

             2.现在来提交这个文件,通过以下命令,如图:

                

                 已经成功提交一个文件,接着可以通过命令git status来查看该文件夹testgit的状态:

                 

                  以上表明工作区没有修改的文件,也没有修改放入暂存区。(每次commit后就会将暂存的修改提交到本地仓库,并清空暂存区)

                 如果该文件夹下的文件没有被修改,直接输入提交commit的命令,则会反馈如下:

                 

                  而文件夹下文件被修改(修改README.md文件),但是没有被添加到暂存区,仍不会被提交到本地仓库,反馈如下:

                   

                     表明该文件夹下有修改,但是没有被添加到暂存区,没有被提交。

                    通过git log 来查看当前分支下的提交记录:

                     

                      发现提交记录只有一条,即为“添加README.md”这一条记录。

 

        3.接下来学习撤销操作,这里先介绍本地文件夹下的一些撤销操作。

              本地工作区下的撤销操作分以下6种情况:

             1.文件修改后没有放入暂存区(即文件一直在工作区),使用git checkout  - -  文件名    来撤销工作区的改动(回到了上次将修改添加到暂存区之后的状态,之后所有在工作区的改动都被清除,进行这项操作之前确定是否清除之后的改动,返回到最近一次add后的状态)

              我已经修改过README.md文件(上面已经演示修改文件,但没有添加到暂存区,直接提交会有什么反应),但是没有添加到文件区,接着命令操作如下图:

              

             cat 文件名   可以查看文件内容,可以看到,操作之前查看文件内容,里面有“222”修改内容

             git checkout - -  文件名       可以将还没有添加到暂存区的修改撤销,我在撤销命令之后再次查看文件内容,发现修改的内容已经被撤销了   

             git checkout .    可以撤销对所有文件的修改 

            2.修改后,修改被添加到暂存区,且文件没有被再次修改(即文件进入暂存区),分两步,先用git reset  文件名   撤销已经被git add操作添加到暂存区的修改(此时修改仍留在工作区),然后执行git checkout - -  文件名     来清除工作区的修改。如图:

               

               可以看到,我又修改了文件内容,并查看了文件内容,且查看了版本库状态,发现该修改没有添加到暂存区也没有提交到版本库。之后添加修改到暂存区,再通过git reset   来将暂存区的修改撤销到工作区中,此时已经被添加到暂存区的修改被作废,修改再次返回到工作区,最后通过git checkout 来撤销工作区的修改。

              3.修改后,文件放入暂存区,且文件被再次修改,分三步:先用git checkout  - -  文件名  撤销工作区的修改,再用git reset  文件名 撤销已经被添加到暂存区的修改,最后执行git checkout  - -  文件名  清除工作区的改动。

              4.修改后,修改已经被提交到本地仓库,想回退到上一个版本,即本地版本回退,如图:

              

              使用git reset --hard HEAD^则返回到上一个版本,返回上上一个版本则是git reset  --hard HEAD^^,如果返回前100个版本则简便命令是git reset --hard HEAD~100

              如果要回退到指定版本号的,则git reset --hard 版本号    ,但是如果不知道版本号的话,可以通过git reflog命令来查看提交记录的版本号。

              5.如果想恢复刚刚被撤销的“修改README.md内容”这一提交的版本,只需要通过git reflog查看该提交的版本号,然后通过git reset --hard  版本号   来恢复。

             值得注意的是,被撤销的提交,使用git log,是查看不到提交记录的,想恢复,只能先通过git reflog查看版本号,然后再git reset,如图:

              

              如图可以看到,提交修改“修改README.md内容”之后,使用git log,发现有两次提交记录,然后git reset之后,再次查看git log,发现提交记录“修改README.md”不见了。

              6.如果在一个分支上比如master进行两项任务的修改A,B,A任务需要今天和明天完成,B任务今天1小时即可提交修改,但是要求每项任务提交修改时,只针对该任务做修改,即某一任务所做的修改,作为一个提交,不是用于解决该任务的修改,则不应该作为该修改被提交。这时候就需要一个保存现场的功能,当任务A被完成到一半(不管是否被添加到暂存区,还未提交到本地仓库),但是需要切换到任务B,如果直接去解决任务B,则会把与任务A相关的修改作为任务B来提交,这时候可以先保存现场,则工作区状态则会是任务A未进行前的状态,这时候进行任务B,将任务B的修改添加到暂存区并且提交,都没有影响。然后恢复现场,则任务A的在工作区的修改没有消失,可以继续进行。

注:对同一个分支进行保存现场,恢复现场,比如上面的例子,这样会使任务B在mster上所做的提交消失(不会消失,如果是同一个分支,两个任务还是会相互干扰,可以在任务B进行完毕后撤销提交,然后再恢复现场,则当前即为任务A的状态),所以一般来说,进行两项任务,可以如果你有一个分支master,在进行任务A,这时先保存现场,然后新建分支dev,dev分支是干净的,里面没有任务A的修改,再将master分支恢复到任务A状态。这样一来,你就有分支mster,进行任务A;分支dev,进行任务B。然后将这两个分支分别与自己的远程仓库合并,这时远程仓库看到的合并所做的提交是独立的,mster的合并是任务A的,里面的提交也是任务A的提交,而不会出现一个合并请求有多个相互干扰的提交。这样有利于远程仓库管理员管理合并请求。因为往往你的远程仓库还要与公司的原仓库进行合并。

  一般解决问题时,在解决之前,不要动工作的主分支,依照它,新建一个分支dev1作为任务A的分支,再新建一个分支dev2作为任务B的分支,两个分支分别向远程仓库提交push请求。任务完成后删除该本地任务分支即可,这样就不需要在一个分支在保存现场等等操作,因为任务很多时,你也不知道你唯一的这个分支在干什么,解决什么问题,放在保存现场的栈中也很麻烦,直接新建分支专门用于解决某个问题。

     如图:

     

       如上,我修改了README.md内容,添加了“3333333”,但是没有提交,查看git status,确实提示有修改没有被提交,然后保存了现场,之后再查git status,发现显示没有修改,查看文件内容,之前添加的修改“3333333”不见了。

        下面我将进行修改,添加“4444444”,然后添加到暂存区,提交到本地仓库master分支,查看提交记录,然后再恢复现场,再次查看文件内容,又恢复到了保存现场之前的状态,如图:

        

         git stash  用来保存工作区的状态,使用后工作区处于最近一次提交后的状态,即工作区无修改,暂存区无保存修改的状态。

         git stash list   查看当前有保存现场的列表,便于恢复指定的现场。

         git stash apply 现场序号  即用来恢复指定现场,但不会删除该现场

         git stach drop 现场序号  删除某个现场

         git stash pop 现场序号  即恢复且删除现场

         删除文件,可以直接在IDE中删除,或者是资源管理器中删除,也可以使用rm 文件名    来删除文件,如果想恢复,撤销删除,则可以使用git checkout --  文件名  来恢复。

        根据上面的操作,此时就可以介绍一些概念:

         工作区:就是我们电脑上可以看到的工作目录,比如上例中的testgit文件夹里的文件(当然不包括.git文件夹以及里面的文件,.git不属于工作区的文件),或者在这个testgit下以后新建的文件都是在工作区。

         版本库:在工作区下,有个目录.git这个就是版本库,即本地仓库,它记录了工作区的文件的所有改动,包括提交的修改,和添加到暂存区的修改,都以某种记录方式记录在这个.git文件夹下。

         暂存区:在版本库中,即在.git里面,有一个区域用来作为暂存区,虽然暂存区在版本库里面,但是添加到暂存区的修改,并没有提交到版本库,可以理解暂存区为中间站,工作区的修改添加到暂存区后,提交到版本库里面才算是将修改送至本地仓库。

 

三.、远程仓库

        远程仓库需要去提供远程仓库的网站中注册使用,公司有自己的远程仓库,使用方法与gitlab.com和github.com差不多,注册(公司的gitlab不需要注册,开发人员找组长开权限即可登录进去)之后还不能够使本地仓库和远程仓库连接起来,将本地仓库文件传送到远程仓库,需要先在本地生成SSH key,这是两个文件,一个是私钥,一个是公钥,然后将公钥文件中的字符串复制后添加到远程仓库平台的自己的账户中,如下:

        1.生成秘钥:ssh-keygen -t rsa -C "你的邮箱地址"        如图:

        

         之后会提示要将秘钥保存到何处,默认即可,接下来全部点回车键即可,然后去默认地址找到公钥id_rsa.pub,打开该文件,全选里面的字符串,复制,

           

         2.将复制的公钥添加到你的远程仓库的账户中,

           

          3.在gitlab.succez.com中自己的账户下,新建一个项目

             

                

                             建立远程仓库成功之后,如下图:

                              

                              红色箭头指向的是该远程仓库的地址,这个地址还有后续作用的。

              4.此时远程仓库建立完毕,远程仓库是个空仓库,想要将自己本地的仓库代码推送到远程仓库,可以在本地仓库下使用命令语句:

                  git remote add origin git@gitlab.succez.com:1417197159/testgit.git              如下图:

                 

                  可以通过git remote -v 来查看本地仓库的链接到的远程仓库地址:

                   

                   这样一来,本地仓库和远程仓库就链接起来了,通过git push origin master 可以将当前分支下的本地仓库内容推送到指定远程仓库的指定分支里,这里origin是指当前远程仓库的名字为origin,当有多个远程仓库时,名字可以是其它的,默认的第一个远程仓库就是origin,而master是指推送到其master分支里。

                    

                 如上,本地仓库的master分支内容已被推送到远程仓库origin的master中,本来远程仓库里什么也没有,连分支master也没有建立,当推送时,发现远程仓库没有该分支,则新建远程仓库的分支,现在在浏览器中查看远程仓库,如下图:

                  

              刚才空的远程仓库已经有了文件内容,和本地仓库一样,成功推送本地仓库内容到远程仓库。

 

              强制推送:当将本地仓库代码commit之后,并且push到远程仓库,这时候想重新修改,撤销上次的push,可以将本地版本先回退,然后git push -f 远程名 远程分支名  ,这样强制提交到远程(如果该远程分支受到protected,是不允许强制推送的,因为此时远程比本地仓库多了一次提交的记录,所以一般远程也有除主分支master之外的其它分支,代码不稳定的时候一般提交到其它分支,一段时间后合并到远程master)

四、分支

       1.新建分支

          

        如上可知,git branch 分支名     则可实现新建本地分支,

        当刚刚fetch了远程分支后,想从远程分支新建一个本地分支,则可通过:git checkout -b 新的本地分支名 远程名/远程分支名

       2.切换分支

          如上可知,git checkout 分支名    则可切换本地仓库的分支

           新建+切换:git checkout -b 分支名    即可实现新建本地分支并切换到该分支

       3.合并分支     

          (1)本地分支之间合并

                   

                    如上可知,master分支里文件内容有修改,并且已提交,而切换到dev分支,查看文件与master分支不同,在dev分支下,使用git merge master 即可使dev分支同步master分支的内容,即当要使分支B拥有分支A的改动,则应该先切换到分支B中,然后使用git merge 分支A,以此来跟新分支B的内容。

          (2)本地仓库与自己的远程仓库合并(严格来说叫推送,但由于本地的分支推送到远程仓库分支不要求两者分支名称一致,所以也有合并的感觉,本地仓库的A分支可以推送到远程仓库的B分支中,如果远程中没有B分支,且远程中有A分支,则会报错;本地仓库A分支可以推送到远程仓库A分支中,如果远程仓库里没有A分支,则远程仓库中会新建该分支再接受推送)

                   

                  如上图,本地master分支推送内容到远程仓库中已有的分支dev中:git push origin dev         (这条命令得在master分支状态下进行)

                                 本地新建了一个分支test,然后将新分支推送到远程仓库中并不存在的分支test中,这时远程仓库会新建test分支,并接受推送的内容。

                            

                 4.查看分支 

                                git branch -v   查看本地仓库的所有分支,并用星号标记当前的分支,如下图:

                                

                                git branch -r      查看远程仓库的所有分支,如下图:

                                 

                                git branch -a     查看包括本地仓库和远程仓库的所有分支

                                  

                 5.删除分支

                     (1)删除本地分支

                               git branch -d  分支名

                                

                     (2)删除远程分支

                               git push 远程仓库名 --delete 该远程仓库的分支名

                               

                               之后登陆网站查看远程仓库,确实没有test分支了。 

                           注:当在网站删除了一个远程仓库的分支,而本地获取到的远程分支已经过时,则通过

                                 git remote update origin --prune   跟新远程分支列表,origin为某个远程仓库名称,,只是一个名称标记,不是指远程仓库里的项目名

                                 

                                 如上图,远程origin里的分支v1,我在远程仓库的网站中将这个分支v1已经删除了,但是通过本地仓库命令查看远程分支列表时仍没有跟新,可通过上列语句跟新远程分支列表。

      五、clone、fetch、pull

              为了使用clone命令,新建一个本地仓库,用来存放待会从远程仓库中克隆的内容。

              1.新建一个本地仓库szbi。(上面有操作截图差不多的操作)

              

              2. 我新建了一个空的本地仓库,然后将公司的bi产品代码克隆到该本地仓库下(bi项目是private项目,只有组长将用户加入该bi项目中作为reporter才有权限克隆代码)

               从上图可以看出,文件个数非常多,要等好久才能克隆完成,为了演示效果,我没有选择分支克隆,git是可以选择分支克隆的,

               git clone 远程仓库地址                          默认克隆该远程仓库下的所有分支

               git clone -b 分支名 远程仓库地址          克隆远程仓库中指定分支的内容

               结果如下图:

               

            注:  根据图发现,克隆是把远程仓库的整个项目包括文件夹也克隆到操作克隆命令的文件夹下了,即szbi文件夹下新建了一个bi文件夹,而且克隆后也会自动使文件夹bi成为一个本地仓库,也就是说,如果要克隆一个项目,这克隆之前要想好克隆的项目放在哪个目录下,并且该目录不用设置成一个仓库,因为克隆下来的项目会自动作为一个本地仓库。

        3.公司的项目,当我们被加入作为reporter时,是不能直接使用git push origin 分支名 来推送代码到公司bi产品的远程仓库中,我们只有clone、fetch、fork的权限,现在说说fetch。

           不能直接推送项目到bi远程仓库,但是我们可以先在网站上fork公司的bi项目到自己的远程仓库中,然后将自己的bi远程仓库链接到本地仓库上,然后每次将本地仓库推送到自己的远程仓库bi中,再在公司bi项目中,进行合并请求,将自己的远程仓库某分支与公司的远程仓库bi项目的某分支进行合并。

            想要跟新自己的本地仓库、自己的远程仓库,使他们保持与公司的bi项目同步,可以在本地仓库的远程origin中fetch代码并合并到本地仓库,然后将合并后的本地仓库内容推送到自己的远程仓库,不过fetch只是拉取代码,并没有合并到本地仓库,需要使用继续使用合并命令才能跟新本地仓库。

            git fetch 远程名 远程分支名    远程分支名可无,此时拉取所有分支到本地

            git  merge 远程名/远程分支名  将某远程下的某分支与当前本地的分支合并               这两条语句可以相当于:git pull 远程名 远程分支名   但操作起来很不好,因为可能远程文件和本地文件出现分歧,最好是查看分歧再合并

             

       4.添加自己fork的bi项目远程仓库地址到该本地仓库中,即添加远程仓库,一个本地仓库是可以添加多个远程仓库的

           git remote add 新的远程名  远程仓库地址

          

           然后我们在本地仓库中编辑项目,提交修改,之后再推送提交到自己的远程仓库里

五、分歧

        1.本地仓库的分支A修改文件text.txt并提交到本地仓库,本地仓库的分支B也修改该文件text.txt并提交到本地仓库,然后在分支B下合并分支A中的修改,此时会出现分歧。如下截图:

           

          分支master与dev同时对README.md进行修改并提交到本地仓库,然后在master分支下合并dev的内容,就会出现冲突,这时候需要修改文件,然后添加到暂存区,之后在提交修改到本地仓库才行。

六、rebase、gitignore

         1.rebase

             假如有1个提交,后来又有两次提交,commit的信息分别为:“第一次提交”,“第二次提交”,“第三次提交”;rebase可以使后来的两次提交都与第一次合并起来,作为一个提交,即作为“第一次提交”。

             git rebase -i 版本号   ,即   将该版本号之后提交的commit与此版本的提交合并,此时,这里的版号应该是“第一次提交”的版号。或者git rebase -i HEAD~n 表示把最近的n次提交合并成一个,即此时n=3

             输入指令后进入vim编辑。应该会出现这样:

              pick 第一次提交的版号

              pick 第二次提交的版号

               pick 第三次提交的版号

      按insert键位,即可输入,然后将第二个,第三个的pick改成squash,即:

              

               pick 第一次提交的版号

               squash 第二次提交的版号

               squash 第三次提交的版号

    然后按esc,此时最下方出现了vi命令输入,输入“:wq”,即可实现保存退出,然后跳回git操作界面,然后进行rebase,中途会跳到vi界面,进行commit message,即合并后的“第一次提交”的新的提交信息。

   git rebase --abort  撤销rebase操作

   此命令适用于一个问题,一个解决提交,一个合并,但是当合并后发现提交的代码还需要在这次基础上修改,重新弄,可以继续在提交的基础上修改代码,然后commit,然后将新的提交合并到上一次的提交中,再合并到远程仓库。

此命令作用于多个commit,最终的结果是:代码的样子还是最后一次提交的样子,只不过rebase后提交的版号是之前的版号。

 

 

        

 

posted @ 2020-06-07 21:31  灵风雨  阅读(197)  评论(0编辑  收藏  举报