工作区、版本库中的暂存区和版本库之间的关系
安装git
yum install -y git
git的身份配置
git config --global user.name 'zqf'
git config --global user.email '826849158@qq.com'
git config --list
user.name=zqf
user.email=826849158@qq.com# 上述的配置实际上是写到了这里:
cat .gitconfig
[user]name = zqfemail = 826849158@qq.com
git常用的操作
初始化一个git仓库
mkdir git_test
cd git_test# 初始化一个git仓库
git init
Initialized empty Git repository in /root/git_test/.git/ll -a
total 0
drwxr-xr-x 3 root root 18 Sep 5 21:38 .
dr-xr-x---. 4 root root 276 Sep 5 21:38 ..
drwxr-xr-x 7 root root 119 Sep 5 21:38 .gitll .git/
total 12
drwxr-xr-x 2 root root 6 Sep 5 21:38 branches # 分支目录
-rw-r--r-- 1 root root 92 Sep 5 21:38 config # 定义项目特有的配置选项
-rw-r--r-- 1 root root 73 Sep 5 21:38 description # 仅供 git web程序使用
-rw-r--r-- 1 root root 23 Sep 5 21:38 HEAD # 指针
drwxr-xr-x 2 root root 242 Sep 5 21:38 hooks # 钩子
drwxr-xr-x 2 root root 21 Sep 5 21:38 info # 包含一个全局排除文件
drwxr-xr-x 4 root root 30 Sep 5 21:38 objects # 存放所有数据内容
drwxr-xr-x 4 root root 31 Sep 5 21:38 refs # 存放指向数据(分支)的提交对象的指针还有一个index,创建了文件提交到暂存区才会有的,用于保存暂存区的内容的
git提交到本地仓库
echo 11111111 > test.txt# 查看当前的状态
git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# test.txt
nothing added to commit but untracked files present (use "git add" to track)# 提交到暂存区
git add . # 从暂存区提交到本地仓库
git commit -m '新建立一个test.txt文件'
[master (root-commit) 7a13d27] 新建立一个test.txt文件1 file changed, 1 insertion(+)create mode 100644 test.txt
git的删除操作
- 删除暂存区的内容: (只是删除暂存区的内容)
echo 22222 >> test.txt
git add .
git rm --cached test.txt
cat test.txt
11111111
22222git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: test.txt
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# test.txtgit commit -m "remove test.txt from repository"
[master b299031] remove test.txt from repository1 file changed, 1 deletion(-)delete mode 100644 test.txtgit status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# test.txt
nothing added to commit but untracked files present (use "git add" to track)# 注意:git rm --cached test.txt只是从暂存区删除了某一个文件,想要删除所有使用如下命令:
git rm --cached `git ls-files`
- 同时删除工作目录和暂存区的内容,前提是没有提交到本地仓库
echo 3333 >> test.txt
git add .
git rm -rf test.txtls # 可以看出工作区的文件也没了
git status
# On branch master
nothing to commit, working directory clean
- 在当前版本删除一个文件的流程(已经提交到了本地仓库)
echo 444444 > test.txt
git add .
git commit -m 'echo 444444 > test.txt'
git rm test.txt # 先在工作目录删除文件
git add . # 提交到暂存区
git commit -m 'del test.txt' # 提交到本地仓库
git status
# On branch master
nothing to commit, working directory clean
对于提交到本地仓库的git文件改名操作
echo 55555 > test.txt
git add .
git commit -m 'echo 55555 > test.txt'git mv test.txt test.sh
git add .
git commit -m '将test.txt名称改为test.sh'
对比各个区域的文件
# 比对当前工作目录和暂存区的不同
git diff# 比对暂存区和本地仓库的不同
git diff --cached
查看历史的git commit快照操作
git log
git log --oneline # 简单一行的显示
git reflog # 查看所有的历史提交(无论是在哪个快照版本下)
显示现在的指针指向到了哪个版本
git log --oneline --decorate
35c4a91 (HEAD, master) 将test.txt名称改为test.sh
b59766b echo 55555 > test.txt
3cf858c del test.txt
333dca5 echo 444444 > test.txt
b299031 remove test.txt from repository
7a13d27 新建立一个test.txt文件
显示每个版本具体的变化内容
git log -p
git log --oneline -p # 简单的显示
git log --oneline -1 -p # 显示最后一个版本的变化信息
git的各个区域覆盖操作
- 从暂存区覆盖到工作目录
cat test.sh
55555
# 这个时候的test.sh中的内容已经提交到了本地仓库,我又写了一个6666到test.sh文件里。
echo 6666 >> test.sh
git checkout -- test.sh
cat test.sh # 发现内容6666已经被覆盖了
55555
- 本地仓库覆盖暂存区
cat test.sh
55555
# 这个时候的test.sh中的内容已经提交到了本地仓库,我又写了一个6666到test.sh文件里。
echo 6666 >> test.sh
git add .
git reset HEAD test.sh
重置后撤出暂存区的变更:
M test.sh
本地仓库回滚版本到工作目录
# 当前工作目录的内容:
cat test.sh
55555
6666
git log --oneline
d348552 echo 6666
35c4a91 将test.txt名称改为test.sh
b59766b echo 55555 > test.txt
3cf858c del test.txt
333dca5 echo 444444 > test.txt
b299031 remove test.txt from repository
7a13d27 新建立一个test.txt文件# 直接回滚到《新建立一个test.txt文件》这个时刻
git reset --hard 7a13d27
HEAD is now at 7a13d27 新建立一个test.txt文件
cat test.txt
11111111
git的tag
# 查看标签
git tag# 创建标签
git tag 标签名字 -m '消息内容'# 推送标签
git push origin 标签名字# 删除标签
git tag -d 标签名字# 推送
git push origin# 给指定的commit打标签
git tag -a v0.1.0 -m 49e0cd22f6bd9510fe65084e023d9c4316XXXXXX# 查看相应标签的版本信息
git show 版本号# 解释:打标签不必要在HEAD之上,也可在之前的版本上打,这需要你知道某个提交对象的校验和,通过git log命令获取。
git的分支
在实际的项目开发中,我们要尽量保证master的分支是非常稳定的,仅用于发布新的版本,平时不要直接修改master里面的数据,工作的时候可以新建不同的分支,等到工作完成之后再合并到master分支上面。
# 查看当前的分支
git branch# 新建一个分支
git branch dev# 切换分支
git checkout dev# 合并分支,在主分支上执行
git merge dev# 删除其他分支
git branch -d dev切换并创建新的分支,会和主分支的内容保持一致
git checkout -b dev
git的冲突合并
比如同一个文件的某一行,主分支和普通分支不同,比如主分支的某一行为:11111,已经提交了,而普通分支的这一行为:22222,也已经提交,这个时候合并会失败,因为这一行冲突了!!
这个时候只能手动解决,进入当前的文件,手动删除或保留(master上的1111还是普通分支的2222)那一行,之后保存再在master分支上 重新提交暂存区,提交本地仓库即可
git的远程操作
git clone
# 在本地仓库克隆一个远程仓库,克隆之后本地仓库和远程仓库的内容一致
git clone +仓库地址
git remote
# 列出所有远程仓库
git remote# 使用-v选项,可以参看远程仓库的网址
git remote -v# 可以查看该仓库的详细信息
git remote show 仓库名# 添加远程仓库
git remote add origin 仓库地址
# origin只是一个仓库名称,可以随意起,添加远程之后,本地目录不会和远程仓库保持一致,使用git pull 拉取之后才会保持一致# 删除远程仓库
git remote rm origin # origin是仓库的名称# 修改远程仓库名称
git remote rename <原仓库名> <新仓库名>
git fetch
# 取回所有分支(branch)的更新到本地
git fetch <远程仓库名># 取回某特定分支的更新
git fetch <远程仓库名> <分支名># 取回origin主机的master分支的更新
git fetch origin master# 所取回的更新,在本地主机上要用"远程仓库名/分支名"的形式读取。比如origin仓库的master,就要用origin/master读取。可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支
git merge origin/master
git rebase origin/master
# merge和rebase的区别下面会有讲解
git pull
# 取回origin仓库的next分支,与本地的master分支合并
git pull origin next:master# 如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin next
git fetch与git pull的区别
git fetch:相当于是从远程获取最新版本到本地,不会自动merge.
git pull:相当于是从远程获取最新版本并merge到本地.
git push
# 推送代码到远程仓库,-u 代表仓库的名称 不一定就是origin
git push -u origin 仓库分支# 省略了本地分支,以下等同,删除origin仓库的master分支
git push origin :master
或者
git push origin --delete master# 不管是否存在对应的远程分支,将本地的所有分支都推送到远程仓库
git push --all origin# 强制推送
git push --force origin# git push不会推送标签(tag),除非使用–tags选项
git push origin --tags
Git reset和revert区别
git reset
reset用于回退版本,可以遗弃不再使用的提交,执行遗弃时,需要根据影响的范围而指定不同的参数,可以指定是否复原索引或工作树内容
当没有指定ID的时候,默认使用HEAD,如果指定ID,那么就是基于指向ID去变动暂存区或工作区的内容
没有指定ID, 暂存区的内容会被当前ID版本号的内容覆盖,工作区不变
git reset指定ID,暂存区的内容会被指定ID版本号的内容覆盖,工作区不变
git reset <ID> 常见参数如下:
--mixed(默认):默认的时候,只有暂存区变化
--hard参数:如果使用 --hard 参数,那么工作区也会变化
--soft:如果使用 --soft 参数,那么暂存区和工作区都不会变化
git revert
在当前提交后面,新增一次提交,抵消掉上一次提交导致的所有变化,不会改变过去的历史,主要是用于安全地取消过去发布的提交
跟git reset用法基本一致,git revert 撤销某次操作,此次操作之前和之后的 commit和history都会保留,并且把这次撤销,作为一次最新的提交,如下:
git revert <commit_id> 如果撤销前一个版本,可以通过如下命令:
git revert HEAD撤销前前一次,如下:
git revert HEAD^
区别
撤销(revert)被设计为撤销公开的提交(比如已经push)的安全方式,git reset被设计为重设本地更改
因为两个命令的目的不同,它们的实现也不一样:重设完全地移除了一堆更改,而撤销保留了原来的更改,用一个新的提交来实现撤销
两者主要区别如下:
git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit
git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容
在回滚这一操作上看,效果差不多。但是在日后继续 merge 以前的老版本时有区别
git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,之前提交合并的代码仍然存在,导致不能够重新合并
但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入
如果回退分支的代码以后还需要的情况则使用git revert, 如果分支是提错了没用的并且不想让别人发现这些错误代码,则使用git reset
Git merge和reabse的相同点和不同点
merge是合并的意思,rebase是复位基底的意思,相同点都是用来合并分支的。
- 不同点: merge操作会生成一个新的节点,之前的提交分开显示。而rebase操作不会生成新的节点,是将两个分支融合成一个线性的提交。
解决冲突时。merge操作遇到冲突的时候,当前merge不能继续进行下去。手动修改冲突内容后,add 修改,commit就可以了。而rebase操作的话,会中断rebase,同时会提示去解决冲突。解决冲突后,将修改add后执行git rebase –continue继续操作,或者git rebase –skip忽略冲突。 - git pull和git pull --rebase区别:git pull做了两个操作分别是”获取”和”合并”。所以加了rebase就是以rebase的方式进行合并分支,默认为merge。
- 总结:选择 merge 还是 rebase?
merge 是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下会提交合并中修改的内容
merge 的提交历史忠实地记录了实际发生过什么,关注点在真实的提交历史上面
rebase 并没有进行合并操作,只是提取了当前分支的修改,将其复制在了目标分支的最新提交后面
rebase 的提交历史反映了项目过程中发生了什么,关注点在开发过程上面
merge 与 rebase 都是非常强大的分支整合命令,没有优劣之分,使用哪一个应由项目和团队的开发需求决定
merge 和 rebase 还有很多强大的选项,可以使用 git help 查看