一、git工作区、暂存区以及版本库
在初始化git版本库之后会生成一个隐藏的文件.git ,可以将该文件理解为git的版本库 repository,而我们自己建立的项目文件夹即工作区 working directory ,在.git 文件夹里面还有很多文件,其中有一个index文件就是暂存区 ,git还为我们自动生成了一个分支master以及指向该分支的指针HEAD,三个的关系具体如下图所示:
1.工作区
就是你在电脑里能看到的目录。
2.暂存区
临时保存修改文件的地方。一般存放在.git下的index文件(.git/index)中。
git add 修改文件 ---- 就是把修改文件放到暂存区中
3.版本库
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
git commit -m “...” ---- 就是把文件存到git仓库
二、配置git
用户名和邮箱地址是本地git客户端的一个变量,每次commit都会用用户名和邮箱纪录。
1.设置用户名
git config --global user.name xxx
2.设置邮箱
git config --global user.email xxx@example.com
三、初始化
1.仓库创建
创建仓库目录
mkdir git_exam
进入仓库目录
cd git_exam
初始化仓库
git init
# Initialized empty Git repository in /data00/home/xxxxxx/go/src/git_exam/.git/
之后会在根目录下生成.git文件夹
2.设置忽略
在根目录下创建.gitignore文件
touch .gitignore
添加忽略名单,如忽略output文件夹,output文件夹在我们现有工程里面都是默认忽略的
echo output .gitignore
将.gitignore文件加入版本管理并提交
四、git基本操作
1.添加文件
工作修改之后,添加文件到暂存区
(1)添加单个文件
git add README.md
(2)添加所有文件
git add .
2.提交文件
从暂存区提交到仓库
(1)提交单个文件
git commit -m "commit message" README.md
(2)提交所有文件
git commit -m "commit message" -a
(3)默认提交所有文件
git commit -m "commit message"
3.查看提交记录
git log
commit 18104a7dc1ff27b90d7342dccd814c4408b8c303
Author: xxxxx <xxxxx@bytedance.com>
Date: Fri Feb 22 19:21:16 2019 +0800
commit message 3
commit b75344f419bf2305354be525da69330f039ed9f0
Author: xxxxx <xxxxx@bytedance.com>
Date: Fri Feb 22 19:10:03 2019 +0800
commit message 2
commit 1edf8527a85c66642313d6a5d5db16f40c833259
Author: xxxxx <xxxxx@bytedance.com>
Date: Mon Feb 18 15:12:25 2019 +0800
commit message 1
git log指令不加其他参数,可以列出所有历史提交,分析如下:
(1)按照提交的时间顺序排列,上层的是更新的提交。
(2).commit后面是经过SHA-1加密算法对此次提交计算的结果,可以唯一标识此次提交,后续成为commit-id。
(3)Author后面分别是提交的用户名和电子邮件地址,它们之间用空格分隔。
(4)Date后面是提交的时间日期。
(5)Date垂直的下方中间以空格分隔的是提交信息说明。
4 查看文件修改状态
列出被修改的文件
git status
和暂存区的内容比较
git diff
和上次提交的内容比较
git diff HEAD
和上上次提交的内容比较
git diff HEAD^
和历史提交(commit-id)的内容比较
git diff commint-id
5.分支操作
(1)列出所有本地分支
git branch
(2)列出所有远程分支
git branch -r
(3)列出所有本地和远程分支
git branch -a
(4)显示本地分支的提交状态
git branch -v
(5)显示本地分支与远程分支的对应关系
git branch -vv
(6)创建分支
git branch 分支名
(7)切换分支
git checkout 分支名
(8)基于当前分支创建并切换分支
git checkout -b 分支名
(9)基于远程分支创建
git checkout -b 本地分支名 远程分支名
(10)强制删除分支
git branch -D 分支名
6.取消工作区的修改
有两种方式:(1)用版本库里面的内容。(2)用暂存区的内容
- 用版本库里面的内容取消文件修改:
(1)单个文件
git checkout HEAD README.md
(2)多个文件
git checkout HEAD README.md SUMMARY.md
(3)所有文件
git checkout HEAD .
关于checkout,除了切换分支、撤销修改以外,还有一个很好的用法,就是快速查看项目旧版本,比如
git checkout commitId
通过传入历史提交的 id,将 HEAD 移动到相应的历史提交处,方便查看历史代码
- 用暂存区的内容取消文件修改:
(1)单个文件
git reset HEAD README.md
(2)多个文件
git reset HEAD README.md SUMMARY.md
(3)所有文件
git reset HEAD .
(4)取消暂存并撤销工作区的修改,以所有文件为例
git reset --hard HEAD .
(5)复位到上上次提交(HEAD代表上次提交)
git reset --hard HEAD^^
(6)复位到历史某一次提交
git reset --hard commitId
7.关联远程远程分支到本地
(1)clone 远程仓库到本地
git clone url
(2)remote 添加远程仓库
git remote add origin url
(3)remote 删除远程仓库
git remote rm origin
(4)remote 查看远程仓库地址
git remote -v
(5)remote 修改远程仓库地址,有三个选项:--add、--delete、--push
git remote origin set-url [url]
(6)push 推送更改到远程仓库
git push
(7)若本地分支和远程分支没有对应上,则可以
git push --set-upstream origin master
或
git push -u origin master
将本地分支和远程分支关联
(8)pull 拉取远程更改到本地并合并
git pull --rebase
五、git实用操作
1.revert撤销某次提交(gitlab把分支合入master后会看到这个命令)
有时候你可能想撤销某次提交,但不想改变提交历史,这时候可以用revert,撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。
(1)先查看提交日志
git log
commit 18104a7dc1ff27b90d7342dccd814c4408b8c303
Author: xxxxx <xxxxx@bytedance.com>
Date: Fri Feb 22 19:21:16 2019 +0800
commit message 3
commit b75344f419bf2305354be525da69330f039ed9f0
Author: xxxxx <xxxxx@bytedance.com>
Date: Fri Feb 22 19:10:03 2019 +0800
commit message 2
commit 1edf8527a85c66642313d6a5d5db16f40c833259
Author: xxxxx <xxxxx@bytedance.com>
Date: Mon Feb 18 15:12:25 2019 +0800
commit message 1
如果相对最后一次提交进行revert,可以执行如下命令:
git revert HEAD
再次查看git log
commit 545952fd83fe0c6ec320bd1e004f4e518967142bAuthor: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:35:26 2019 +0800Revert "commit message 3"commit 18104a7dc1ff27b90d7342dccd814c4408b8c303Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:21:16 2019 +0800commit message 3commit b75344f419bf2305354be525da69330f039ed9f0Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:10:03 2019 +0800commit message 2commit 1edf8527a85c66642313d6a5d5db16f40c833259Author: xxxxx <xxxxx@bytedance.com>Date: Mon Feb 18 15:12:25 2019 +0800commit message 1
2.git rebase master
我们在作分支合并的时候最常用的就是merge操作,但是执行merge之后,会产生一个新的commit,例如:Merge branch 'branch-1'。这个commit把两个branch合并到一起并作了一次新的提交。但是,如果使用rebase的话就会避免这个问题。我们来看一个例子,下边是我分别用merge和rebase之后的git log。
如果我们有一个分支master,现在master上有两个提交:c1、c2,如下图所示:
master /c1 - c2
如果此时我们基于master新建一个分支:
git checkout -b git_exam master
此时git的commit记录指向如下:
master /c1 - c2 \ git_exam
我们在git_exam上提交了更改:c3、c4,另外一个同事在master上提交了更改:c5、c6,此时分支结构如下:
master / c5 - c6 /c1 - c2 \ c3 - c4 \ git_exam
如果我们想把c5 c6更改线性的合入我们的分支,可以执行如下命令:
git checkout master #切换到master分支
git pull --rebase # 拉取master的最近更新,并线性合并
git checkout git_exam # 切换到我们自己的分支
git rebase master # 把git_exam的提交历史和master的提交历史线性合并
在git_exam分支执行git rebase master,git具体完成的操作主要有下:
git会先把你的git_exam分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把git_exam分支更新 为最新的master分支,最后把保存的这些补丁应用到git_exam分支上。
以上命令执行完以后具体的分支指向大体如下:
master /c1 - c2 - c5 - c6 - c3 - c4 \ git_exam
3.解决rebase过程中的冲突
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,执行如下命令去更新内容的索引(index):
git add 解决冲突后的文件
然后,你无需执行 git commit,只要执行:
git rebase --continue
这样git会继续应用(apply)余下的补丁。
在任何时候,你可以用--abort参数来终止rebase的行动,并且git_exam分支会回到rebase开始前的状态。
git rebase --abort
4.git rebase 和 git merge的区别
git merge 是用来合并两个分支的。
git merge b # 将b分支合并到当前分支
同样
git rebase b # 也是把 b分支合并到当前分支
对与git rebase master一节中,如果使用git merge master,会生成一个新的commit用来表示合并操作,具体的分支指向结构图如下:
master / c5 - c6 /c1 - c2 - c5 - c6 \ \ \ c7 - git_exam \ / c3 - c4
5.git的变基/把多次提交合并为一个
当你想对历史某一次提交进行修改,又不想增加新的提交时,可以使用变基操作。
比如:你正在进行开发,你发现有个参数名写错了,属于小问题,而这个参数正是你历史提交中某一次引入的,你想修改这个参数名而不产生新提交,这时候可以使用变基:
git rebase -i commit-id
# commit-id 是最后一次不需要合并的提交id
执行git log命令
commit 545952fd83fe0c6ec320bd1e004f4e518967142bAuthor: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:35:26 2019 +0800Revert "commit message 3"commit 18104a7dc1ff27b90d7342dccd814c4408b8c303Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:21:16 2019 +0800commit message 3commit b75344f419bf2305354be525da69330f039ed9f0Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:10:03 2019 +0800commit message 2commit 1edf8527a85c66642313d6a5d5db16f40c833259Author: xxxxx <xxxxx@bytedance.com>Date: Mon Feb 18 15:12:25 2019 +0800commit message 1
如果我想把以下三个分支合为一个提交,毕竟commit message 3的提交最后被revert 了
b75344f419bf2305354be525da69330f039ed9f0 --- commit message 218104a7dc1ff27b90d7342dccd814c4408b8c303 --- commit message 3545952fd83fe0c6ec320bd1e004f4e518967142b --- Revert "commit message 3"
那么最后一次不需要合并的commit-id就是
1edf8527a85c66642313d6a5d5db16f40c833259 --- commit message 1
可以执行如下命令:
git rebase -i 1edf8527a85c66642313d6a5d5db16f40c833259
执行完上述命令会弹出编辑框:
pick b75344f commit message 2pick 18104a7 commit message 3pick 545952f Revert "commit message 3"# 变基 4220233..545952f 到 4220233(3 个提交)## 命令:# p, pick <提交> = 使用提交# r, reword <提交> = 使用提交,但修改提交说明# e, edit <提交> = 使用提交,进入 shell 以便进行提交修补# s, squash <提交> = 使用提交,但融合到前一个提交# f, fixup <提交> = 类似于 "squash",但丢弃提交说明日志# x, exec <命令> = 使用 shell 运行命令(此行剩余部分)# b, break = 在此处停止(使用 'git rebase --continue' 继续变基)# ...
采用融合到前一个提交的方式:
修改如下:
pick b75344f commit message 2s 18104a7 commit message 3s 545952f Revert "commit message 3"# 变基 18104a7..545952f 到 b75344f(3 个提交)## 命令:# p, pick <提交> = 使用提交# r, reword <提交> = 使用提交,但修改提交说明# e, edit <提交> = 使用提交,进入 shell 以便进行提交修补# s, squash <提交> = 使用提交,但融合到前一个提交# f, fixup <提交> = 类似于 "squash",但丢弃提交说明日志# x, exec <命令> = 使用 shell 运行命令(此行剩余部分)# b, break = 在此处停止(使用 'git rebase --continue' 继续变基)# ...
保存后会弹出编辑框:
# 这是一个 3 个提交的组合。# 这是第一个提交说明:commit message 2Change-Id: b75344f419bf2305354be525da69330f039ed9f0# 这是提交说明 #2:commit message 3Change-Id: 18104a7dc1ff27b90d7342dccd814c4408b8c303# 这是提交说明 #3:Revert "commit message 3"This reverts commit 545952fd83fe0c6ec320bd1e004f4e518967142b.# 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交# 说明将会终止提交。## 日期: Tue Mar 5 09:50:59 2019 +0800## 交互式变基操作正在进行中;至 4220233# 最后的命令已完成(3 条命令被执行):# squash 18104a7 remove commit message 3# squash 545952f Revert "commit message 3"# 未剩下任何命令。# 您在执行将分支 'working' 变基到 '4220233' 的操作。
把没有注释的删除,改成你想要的提交提示语,保存即可
# 这是一个 3 个提交的组合。# 这是第一个提交说明:commit message 2# 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交# 说明将会终止提交。## 日期: Tue Mar 5 09:50:59 2019 +0800## 交互式变基操作正在进行中;至 4220233# 最后的命令已完成(3 条命令被执行):# squash 18104a7 remove commit message 3# squash 545952f Revert "commit message 3"# 未剩下任何命令。# 您在执行将分支 'working' 变基到 '4220233' 的操作。