git是个非常强大的版本管理工具,但是初学时往往一头雾水。其实常用的git功能往往固定的几个命令就可以胜任,下面会列举我在实际开发中实用到的git命令和对应场景,相信可以应对大部分的开发情况了。
想要实用好git,仓库的概念必须要有,具体有几个概念:
工作区:就是当前正在编辑的内容所在的区域,其中的文件随着开发进度而改动或者删减。
暂存区:顾名思义,就是将需要暂存的内容提交到的区域,暂存区的内容可以退回的工作区。添加到暂存区可以理解为对文件建立跟踪。
版本库:一般当某些修改确定了,就可以通过暂存区提交到版本库,通常会给提交的版本一些注释。
远程仓库:是远程端的代码仓库,可由本地版本库提交至远程仓库。
这个命令可以看出三个部分的内容,工作区较版本库里有改动的内容,工作区较版本库里未跟踪上的内容,暂存区的内容,示例如下图所示。其中one.txt是暂存区内容,README.md是工作区修改内容,New_add是未跟踪的内容。
将工作区的内容添加到暂存区,上面的截图就是下图情况执行git add one.txt后的情况,git add后面可以接一个文件,也可以接多个文件,还可以用git add . 将当前文件夹所有的改动文件都加入到暂存区,这个使用时要非常的注意,如果当前文件夹是整个工程,使用git add. 会将所有的改动文件都加入暂存区,包括不是你负责修改的模块,这样可能就会和远程版本库起冲突,所以慎重使用。一般git add 只添加自己负责修改的部分进入暂存区。
将暂存区的内容添加到本地代码库,本地代码库可以理解为本地代码修改的正式版本存放位置,一般存放到代码库的版本都是较为正式的版本。git commit 后会添加一些对当前代码的描述内容,分配版本号,方便后续查找。
远程仓库一般就是和本地代码库进行交互,和远程仓库相关的操作就需要更加的谨慎。因为这一般是存放大家共同认可的代码版本,如果推送不当,会对团体的协作带来不必要的麻烦。
Git push,经常用的操作是将本地的代码版本推送到远程仓库的分支,通过git push 来完成。使用格式为:git push <远程主机名><本地分支名>:<远程分支名>。一般来说,本地仓库只会和一个远程仓库建立连接,这样远程主机名就只会是origin。之后明确本地分支和远程分支,是表明要将本地哪一个分支的本地版本库的代码推送到远程的一个特定的分支。如果本地分支已经与远程分支建立了连接,可以省略,直接git push。
除了将本地代码推送到远程代码库,还经常需要将远程代码库中的代码拉取到本地。因为在团队协作中,经常需要同步别人修改的代码。但是往往git pull时会经常存在问题,因为别人的修改可能会和你本地的修改有冲突,或者你本地的一些方便调试的修改虽然没有push到远程代码,但是也不想在拉取远程代码的时候被覆盖掉。所以通常情况下,我们并不直接拉取远程的分支到本地正在工作的分支上。
首先拉取远程分支代码到本地的一个新分支:
git fetch origin 远程分支名x:本地分支名x (不切换新分支)
git checkout-b 本地分支名x origin/远程分支名x (切换到新分支)
然后将当前工作分支的工作区和暂存区的修改保存到git栈中:
git stash
再将拉取下来的分支,merge到当前工作的分支,注意merge不会删除未跟踪区域的内容
git merge
最后将git栈中的修改还原回来
git stash pop
实际过程演示:
注意看,当前远程代码库的main分支比本地版本库中的分支要超前。
先拉取远程分支到一个新分支,通过git fetch拉取远程分支到本地新建分支,但不与远程分支建立关联。
看一下当前分支的状态,工作区有修改未提交,不能直接merge,先将工作区的修改通过git stash放到git的栈中,然后使用git merge temp_main将刚刚pull下来的新版本分支merge到当前工作分支。
同步代码后,将自己想要暂时保存但又不想提交的工作区修改pop回来。注意看,pop前后工作区的修的内容是不同。另外需要注意的是,整个merge操作不影响未跟踪区域的内容,所以未跟踪区域的内容是始终保留的。
这里本地对test1 file 文件进行了修改,远程仓库其他人对readme 文件进行了修改,这两个修改是不冲突的,但是对于本地文件的版本和远程文件的版本,就会显示本地落后一版又超前一版的情况。这个时候如果直接pull远程代码到本地,或者直接push本地代码到远程,都会被拒绝。会提示! [rejected] main ->main (non-fast-forward)。
这时候的解决方法可以参考上面的merge操作,先本地新建一个分支,拉取远程分支,再merge。注意,切换本地分支的时候,有未跟踪的文件不影响切换,有未add或未提交的会影响。
拉取后,切换到main分支,将mainback merge到main中,因为没有冲突,所以merge的过程很顺利,然后当前的main中因为已经同步了远程的代码,并且本地又有修改,所以状态已经是本地比远程版本领先2版,而不是落后1版领先1版。这时候就可以顺利push了。
经是本地比远程版本领先2版,而不是落后1版领先1版。这时候就可以顺利push了。
如下图所示:
往往现实中的情况不会那么理想,有可能本地修改和远程修改的是一个文件,那么这是后不仅仅是版本的冲突,还有修改内容的冲突,这时候按照上面的步骤,在merge的时候就会需要额外处理冲突。
同样保险起见先新建一个备用分支conflictback, 然后拉取远程的conflict分支的代码,这时候就会提示有冲突(或者先之间本地创建直接拉取远程代码)。
然后我们找到冲突的文件conflict.cpp,选择接受远程还是本地的修改,也可都接受。修改完成后,重新add和commit。
这一这时候conflictback的版本已经是merge之后的版本了。然后切回conflict分支,再将conflictback的分支merge回来。这样同步远程代码并修改冲突就完成了。
修改完成后,可以再推送一版当前分支到远程代码库。推送时就不会产生冲突。