Git 入门笔记
一、什么是 Git??
git
一个分布式的版本控制系统
gitkraken
一个可视化的 git 管理工具
github
一个 git 的远端仓库(同类的还有 gitlab、gitee 等)
所以,不要把 git 和实验室的 gitlab 混为一谈。git 是管理版本的工具,是对于本地代码的管理;而 gitlab 是一个远端仓库,用于存放 git 管理的代码。
二、了解 Git
所以我们现在先抛开远端仓库,用 git 管理好本地代码先吧!
git 的三个区域(空间维度):
- 工作区域(Working Directory):也就是平时存放代码的地方
- 暂存区域(Stage):用于临时存放你的改动,事实上它只是一个文件,保存即将提交的文件列表信息
- Git 仓库(Repository):是安全存放数据的位置,这里边有你提交的所有版本的数据。
在本地提交代码基本上就是这三个状态的转换
git 文件的四个状态:
- 未跟踪(untracked):新文件,没被添加进暂存区过
- 已修改(modified):对应了在工作区内修改了文件
- 已暂存(staged):对应了已经把修改的文件提交到暂存区域
- 已提交(committed):将暂存区域提交到一个新的版本,工作区回归未修改状态
git 的版本(时间维度):
截取自 http://bramus.github.io/ws2-sws-course-materials/xx.git.html 每一次 commit 都会根据提交的内容和人计算出哈希值作为这个 commit 的 id。
HEAD
是一个指针,指向当前的状态的 commit;HEAD~
则是指向上一个 commit 的指针(如图为 1d7a184),HEAD~X
则是指向上 X 个 commit 的指针。
三、上手 Git!
来了老弟
首先,git 为了辨别是谁提交的代码,你必须设置你的 username 和 emial
1
2git config --global user.name "your name"
git config --global user.email "your@email.com"这仅仅是给 git 辨别提交代码的身份用,你喜欢设置假的或者用我的名字上传我也一点办法也没有。
以上代码是设置全局的,如果你只想这个用户名和邮箱只对此工程有效,去掉
--global
即可。然后就可以初始化仓库
1
git init
至此我们的工程已经进入了由 git 支配的世界
工作区 -> 暂存区
我们可以用以下命令查看目前版本库的状态:
1
git status
顺便插播
status
的部分选项:选项 说明 -s
(--short
)以短格式输出 -b
(--branch
)显示分支和跟踪信息 ... ... 如果你刚刚
init
了一个 git 仓库,那么你会发现你的文件处于 untrack 的状态;如果你刚刚修改了某个文件,那么你会发现被修改的文件处于 unstage 状态;
此时我们需要用以下命令将这些文件添加到暂存区中:
1
git add yourfile
特殊用法:
命令 说明 git add -A
提交所有变化 git add -u
提交被修改 (modified) 和被删除 (deleted) 文件,不包括新文件 (new) git add .
提交新文件 (new) 和被修改 (modified) 文件,不包括被删除 (deleted) 文件 暂存区 -> Git 仓库
接下来就是提交代码环节了!
1
git commit -m "your commit message"
但是往往事情没有那么简单,有的人提交了代码后发现,好像落了点什么,不要着急不要回退。将新更改好的版本
add
到暂存区后,使用以下命令将这次改变合并到之前的 commit 中:1
git commit --amend
如果不需要修改 commit message 的话,还可以加上
--no-edit
!查看状态
如果说上文的
status
能查看空间维度的状态的话,以下命令就能查看时间维度的状态:1
git log
log
提供了不少的选项,以下列出少许常用的,更多的建议自行搜索:选项 说明 --graph
显示 ASCII 图形表示的分支合并历史。 --oneline
只显示提交 ID 和提交信息的第一行 ... ... 接下来的命令用于找不同:
1
git diff
以下表格很重要:
比较工作区与上次 commit 比较暂存区和上一次 commit 比较工作区和暂存区 git diff
git diff --cached
git diff HEAD
工作区下列命令是对 git 文件进行删除、重命名:
1
2git rm fileA.cpp # 从git中删除fileA.cpp文件
git mv fileB.cpp fileC.cpp #将fileB.cpp重命名为fileC.cpp暂存修改
除了 commit,我们还可以用如下命令安全的存放你的现在的状态哦
1
git stash
用如下命令就可以恢复暂存了
1
git stash pop
四、穿越时间
欲想穿越,就要搞懂分清两个命令 reset
和 checkout
reset
使用如下命令可以将 HEAD 分支移到前一个 commit
1
git reset HEAD~
当然也可以把
HEAD~
替换成你想到达的分支名、commit id!注意以下区别:
命令 说明 git reset --mixed
(默认)修改版本库、暂存区 git reset --soft
修改版本库 git reset --hard
修改版本库、暂存区、工作区 用
git log
一看,为什么我回到前一个 commit 之后原来的就消失了!??不着急,我们可以使用以下命令找回你的 commit id 和 HEAD 指针!
1
git reflog
而且
reset
还可以单独修改个别文件1
git reset [版本] [文件名或路径]
checkout
使用如下命令可以把 HEAD 指针移到某个分支
1
git checkout [branchname]
当然也可以把分支名替换成 HEAD 指针、commit id!
那么,
checkout
和reset
又有什么区别!!?图片描述 最重要的区别在于
reset
会移动 HEAD 所指向分支的指向,而checkout
只移动 HEAD 指针本身!这样带来了个问题,使用 checkout 你可以指向一个并没有任何分支指向的 commit!此时 git 便会帮你创建一个匿名分支!在匿名分支上的所有操作在你切换到别的分支时会被全部丢弃!
五、分支
你的第一个分支
使用以下命令查看分支状况:
1
git branch
使用以下命令创建名为 develop 的分支,并切换到新分支下:
1
2git branch develop # 创建分支
git checkout develop # 切换到develop分支下或者使用下面命令偷懒!
1
git checkout -b hotfix # 创建并切换到hotfix分支下
merge 合并!
以下命令将 develop 分支合并到 master 中:
1
2git checkout master # 首先要切换到master分支!
git merge develop # 将develop分支merge到master中要注意的是,使用以上命令,git 会采用默认的
Fast forward
格式进行merge
(因为此时 develop 分支比 master 分支新),这样merge
的这次操作不会有commit
信息,log
中也不会有分支的图案。我们可以采取--no-ff
这种方式保留merge
的commit
信息:1
git merge --no-ff -m "commit message" develop
燃鹅很多时候时期并没有那么简单,更多时候在 merge 之后便会报告合并出现了冲突!git 会在有冲突的文件下作形如以下的标记:
1
2
3
4
5<<<<<<< HEAD
# edited in master
=======
# edited in develop
>>>>>>> develop这时,
# edited in develop
和# edited in master
发生了冲突,当我们手动处理好冲突之后就可以commit
代码啦!此时,删除 develop 分支也不会有什么影响啊(仅删除了 develop 分支的指针):
1
git branch -d develop
rebase
文字功底匮乏,请看图!
重新划分分支冲突 重新划分分支冲突 重新划分分支冲突 重新划分分支冲突 故事是这样的,原本在 branch-A 的 C3 基于了 C1 来开发。突然程序出现了个惊天大 bug,情急之下新建了分支 branch-B 修复了惊天大 bug。但是 C3 当然也想在无惊天大 bug 的代码下进行开发呀!于是便把分支 branch-B
rebase
到了 branch-A 中,此时 C3*(这时的 C3 已经不是往年的 C3,是没有惊天大 bug 的 C3,故加 *)已经变成了基于 C4 开发了!1
git rebase develop
在处理冲突之后,使用以下命令就可以成功的 rebase 啦
1
git rebase --continue
注意!rebase 会无情修改别人的 commit!如图 C2、C4
六、远端仓库
查看远端仓库:
1 | git remote |
加上 -v
可显示需要读写远端仓库使用的 Git 保存的简写与其对应的 URL。
查看某远端仓库更多信息:
1 | git remote show [remote-name] |
添加远端仓库:
1 | git remote add [shortname] [url] |
克隆远端仓库:
1 | git clone [url] |
从远端仓库中获得数据:
1 | git fetch [remote-name] |
如果你有一个分支设置为跟踪一个远端分支,可以使用 git pull
命令来自动的抓取然后合并远端分支到当前分支:
1 | git pull [remote-name] |
查看本地分支和远端分支的跟踪关系:
1 | git branch -vv |
推送到远端仓库:
1 | git push [remote-name] [branch-name] |
跟踪一个远端分支:
1 | # 设置一个已有的本地分支跟踪一个刚刚拉取下来的远端分支 |
远端仓库重命名:
1 | git remote rename |
删除远端仓库:
1 | git remote rm |