Git的使用与版本控制
所有的素材均来自于https://morvanzhou.github.io/tutorials/others/git/。本文只是个人学习的笔记记录,如果想要学习,强烈建议去听听Morvan老师的课程,一听就懂,一学就会。
基本配置与操作
创建版本库 (init)
- 通过iTerm2 cd到版本库所在的文件夹下
- 通过命令
$ git init
来建立新的git管理库
添加文件管理 (add)
$ git status
用于查看版本库的状况(包括文件所处的状态:untracked/tracked/modified/unmodified…;$ git add [filename]
用于将文件加入版本库,使之成为staged状态;$ git add .
可以将文件夹中所有未被添加的文件加入版本库;
提交改变 (commit)
$ git commit -m "comment"
命令将staged状态的文件commit成umodified状态,利用comment来注释本次修改的内容,以便后期查阅
修改记录
log
$ git log
可以查看详细的修改记录$ git log --oneline
可以查看修改记录的简要信息
status
$ git status
用于查看版本库的状况(包括文件所处的状态:untracked/tracked/modified/unmodified…$ git status -s
可以查看缩略版的版本库状况
diff
$ git diff
用于查看还没被add,也就是处于unstaged状态的修改部分和上一个commit的文件的区别$ git diff --cached
用于查看已经被add,也就是处于staged状态,但是未被commit的修改部分与上一个commit的文件的区别$ git diff HEAD
用于查看已经被add和未被add,但是均为被commit的内容与上一个commit版本的区别
# 对比三种不同 diff 形式
$ git diff HEAD # staged & unstaged
@@ -1 +1,3 @@
-a = 1 # 已 staged
+a = 2 # 已 staged
+b = 1 # 已 staged
+c = b # 还没 add 却 stage (unstaged)
-----------------------
$ git diff # unstaged
@@ -1,2 +1,3 @@
a = 2 # 注: 前面没有 +
b = 1 # 注: 前面没有 +
+c = b # 还没 add 去 stage (unstaged)
-----------------------
$ git diff --cached # staged
@@ -1 +1,2 @@
-a = 1 # 已 staged
+a = 2 # 已 staged
+b = 1 # 已 staged
```
版本回退
amend
在上一个版本中添加一个新文件,可以使用$ git commit --amend --no-edit
来操作,其中的“–no-eit"表示不编辑, 直接合并到上一个 commit
reset
当文件通过add操作后,处于staged状态后,回到add之前的状态,可以利用$ git reset [filename]
来实现。其本质是利用reset,使状态指针回到上一个commit的版本。
- 对于以下情况的记录,
$ git log --oneline
# 输出
904e1ba change 2
c6762a1 change 1
13be9a7 create 1.py
```
(1) 回到change2状态
$ git reset --hard HEAD
(2) 回到change1状态
$ git reset --hard HEAD^
$ git reset --hard c6762a1
(3) 回到更后面的状态
$ git reset --hard HEAD~3
表示回到前面第三个状态,~3表示3个^$ git reset --hard [id]
用状态id直接回到改状态
如果回到过去后还想回到将来,可以首先通过$ git reflog
来查看所有对HEAD指针做过的改动,并找到目标的commit id,例如下面这种情况,回到了change 1状态后,想再回到change 2,可以发现change 2的状态(在change 2做了amend的行为,所以id=904e1ba)
$ git reflog
# 输出
c6762a1 HEAD@{0}: reset: moving to c6762a1
904e1ba HEAD@{1}: commit (amend): change 2
0107760 HEAD@{2}: commit: change 2
c6762a1 HEAD@{3}: commit: change 1
13be9a7 HEAD@{4}: commit (initial): create 1.py
$ git reset --hard 904e1ba
checkout
利用$ git checkout [commit_id] -- [filename]
来指定对某一个file,回到具体某一个commit id时的版本状态。
分支管理
查看分支
通过$ git log --oneline --graph
可以查看图形化的master和branch情况
建立分支
分支的作用通常用于开发版本的建立和公开版本的维护。通过分支branch和master的搭配可以在不影响主版本的情况下进行新版本的开发和调试。
branch方法
通过$ git branch [branch name]
的方式进行分支的添加
checkout方法
通过$ git checkout -b [branch name]
的方式可以直接添加一个新的branch并将指针移到该branch中。此外,如果已经建立了新的branch可以通过$ git checkout [branch name]
的方式切换分支
分支中操作
在分支中的修改
$ git commit -am "[comment]"
的方式可以将修改的文件直接add
并进行-m
的comment
操作。这种情况下,如果该文件事先不在repo中是无法操作的(需要amend操作将文件先加入版本库中)
将分支的内容push到master中
- 首先要切换到master中,才能将branch的内容push过来,用
$ git checkout master
来进行切换 - 使用
$ git mergh --no-ff -m "[comment]" [branch name]
的操作方式,将其他版本的数据合并到当前的master版本中。其中,--no-ff
的参数表示,不使用$ git merge
默认的Fast forward格式进行merge的操作(因为那样不会保留commit信息),log中也不会保留graph。
分支冲突的解决
merge方法
当修改同时发生在master(C3)和一个branch(C4)中时,要将master合并branch的内容会产生分支冲突的情况(C4和C3的前序文件信息不同),此时会在master的该文件中报错:
a = 1
# I went back to change 1
<<<<<<< HEAD
# edited in master ###在master中的信息
=======
# edited in dev ###在被合并的分支中中的信息
>>>>>>> dev
此时,需要将master中的该文件进行手动处理,并提交commit
即可$ git commit -am "solve conflict"
,此时的log文件会显示出冲突和合并的情况:
$ git log --oneline --graph
# 输出
* 7810065 solve conflict ###冲突解决后的log信息(和commit id)
|\
| * f7d2e3a change 3 in dev ###*在分支
* | 3d7796e change 4 in master ###*在master
|/
* 47f167e back to change 1 and add comment for 1.py
* 904e1ba change 2
* c6762a1 change 1
* 13be9a7 create 1.py
rebase方法
假设共享的 branch 是 branch B
,而我在 branch A
上工作, 有一天我发现branch B
已经有一些小更新,我也想试试我的程序和这些小更新兼不兼容, 我也我想合并, 这时就可以用 rebase
来补充我的分支branch B
的内容。补充完以后,和后面那张图的 merge
不同,我还是继续在 C3
上工作,不过此时的 C3
的本质却不一样了,因为吸收了那些小更新。所以我们用 C3'
来代替。
可以看出 rebase
改变了 C3
的属性,C3
已经不是从 C1
衍生而来的了。这一点和 merge
不一样。merge
在合并的时候创建了一个新的 C5
commit
。这一点不同,使得在共享分支中使用 rebase
变得危险。如果是共享分支的历史被改写。别人之前共享内容的 commit
就被你的 rebase
修改掉了。
### 在自己的分支上(C3)使用rebase。
$ git rebase [branch name]
### 这时候一定会出现报错并给予提示:
#When you have resolved this problem, run "git rebase --continue".
#If you prefer to skip this patch, run "git rebase --skip" instead.
#To check out the original branch and stop rebasing, run "git rebase --abort".
###当在自己的branch完成修改后可以选择以上三种方式,继续rebase(git rebase --continue)/跳过本次rebase(git rebase --skip)/直接放弃rebase(git rebase --abort)
临时修改
Stash方法
当在分支上做代码调试和修改时,突然来了新的需求,这时候需要对手头的工作进行临时储存(不选择进行直接commit是为了保持每一次commit的内容都是有价值的,否则之后的log会非常难看)。这时候就可以选择使用$ git stash
对代码进行临时的储存,然后切换其他分支进行操作完后,回到本分支使用$ git stach pop
调出之前暂存的内容,就可以继续愉快的coding啦。
在线管理GitHub
对于本地已经git init
了的git管理库,使用
$ git remote add origin https://github.com/xxx/xxx.git
$ git push -u origin master # 推送本地 master 去 origin
$ git push -u origin dev # 推送本地 dev 去 origin
就可以上传到在线的github管理库中了。
over