Git详细使用大全- rebase, merge, switch, cherry-pick, tag

Git2.3 目录


推荐阅读

前言-各个版本控制工具对比

版本控制工具:控制代码版本,避免混乱。

集中式版本控制工具

  • CVS
  • SVN
  • VSS

分布式Git

自己拥有完整的版本。
在这里插入图片描述

Git分区

在这里插入图片描述

工作流程

  1. git clone下远程仓库
  2. git checkout选择分支
  3. git add <filename>文件放到暂存区
  4. git commit提交修改到仓库
  5. git push repo branch添加到远程仓库
    在这里插入图片描述

0.配置

查看签名

cat ./.git/config

设置签名

git config user.name name, git config user.email email

查看签名文件

~/.gitconfig

设置例子

git config --global user.name name
git config --global user.email email

1. 版本库与文件操作

1.1 创建版本库

进入目录后,执行初始化:
git init 或者 .git/

  • 创建成功,会在仓库文件夹下面生成.git目录
  • .git:跟踪管理版本库
  • 自动创建唯一master分支

1.2 添加文件到仓库

  1. git add <filename>
  • 此举将文件放进暂存区(stage)
  • 可反复使用
  • 可同时添加多个文件
  1. git commit -m <message>
  • 把暂存区的所有内容提交到当前分支
  • 添加到版本库,message是提交描述

1.2.1 查看仓库状态

git status
查看工作区的状态,常见的结果:

  1. Changes not staged for commit: 文件更改了,但未放入暂存区,需要add
  2. Changes to be committed: 文件已经放入暂存区,但未提交到版本库,需要commit
  3. Untracked files: 表示该文件从未被添加到版本库

1.2.2 查看修改内容

如果使用git commit -m <message>,被告知文件被修改过:

  • 使用git diff <filename>,查看修改内容
  • add文件之前使用此查看

1.2.3 提交修改

提交修改与提交新文件相同:

  1. add
  2. commit
  • 需要提交的文件修改,暂时放在暂存区,然后一次性提交暂存区的所有修改

1.3 版本回退

  1. 当修改到一定程度时,需要对文件进行备份,此时的备份也可以看作是快照,即为git commit -m <message>
  2. 当做出错误行为,改错文件,误删文件,可以从最近的commit里恢复

回退操作

  1. git log可以查看提交历史,版本库的状态,并显示从近到远的提交日志

  2. git log --pretty=online简化输出,每个日志单独成行

  3. Head表示当前的版本,而前面的则是commit id代表着版本号
    在这里插入图片描述

  4. git reset --hard HEAD^回退到上一版本

    • HEAD表示回退1个版本,新版本表示不变
    • HEAD^表示回退2个版本,废除
      以上两个在新版本(2.3.0)中都已出现误差,只能使用以下
    • HEAD~n表示回退n个版本,HEAD是个指针
  5. git reset --hard 新版本的commit id返回过去/未来的版本

    • commit id可以只写id的前7位,git会自动寻找
      在这里插入图片描述
  6. git reflog查看命令历史,确定要回到的未来版本
    在这里插入图片描述

1.4 工作区和暂存区

  • 工作区:当前的工作目录
  • 版本库:工作区里隐藏的.git目录
  • 暂存区(stage/index):存放在版本库中,但没有提交(最重要的区)
  • 版本库里,放着第一个分支master,以及指向master的指针HEAD
    在这里插入图片描述

流程

  • git add <filename>提交到暂存区
  • git commit -m <message>一次性提交所有修改

注意

  • Git跟踪的是修改,而非文件
  • 如果不git add到暂存区,就不会加入到commit

查看工作区和版本库的差别

  • 提交后,git diff HEAD -- <filename>可以查看工作区版本库最新版本的区别
    在这里插入图片描述

  • 此命令与git diff <filename>相同

diff的补充

  • git diff工作区(work dict)和暂存区(stage)的比较,上次git add的内容
  • git diff --cached暂存区(stage)和仓库分支(master)的比较,上次git commit的内容

1.5 撤销修改

  1. 改乱了工作区的某个文件,直接丢弃工作区的修改时:git checkout -- <file>
    • 仅限于修改内容
    • 如果文件删除,需要用git checkout branch filename
    • 文件修改后未放到暂存区,撤销修改回到和版本库一样的状态
    • 文件已经添加到暂存区,撤销修改回到添加到暂存区后的状态
  2. 改乱了工作区文件内容,还添加到暂存区,丢弃修改需要两步:
    • git reset HEAD <file>暂存区的修改撤销掉,重新回到工作区
    • 工作区git checkout -- <file>,回到未修改前
  3. 已经提交到版本库,想要撤销本次提交,需要版本回退,前提是没有提交到远程库
    • git checkout branch filename是用版本库替换工作区
    • git checkout获取变化的地方

---的补充

  • -后跟短命令选项,通常是单字母,如-m
  • --后跟长命令选项
    • 如果后面不跟任何选项,表示命令选项结束,后面都是命令的参数而非选项
    • git checkout -- filename,filename是参数而不是选项

1.6删除文件

  • 在删除文件后,执行git add/rm <filename>
  • git commit -m <message>提交到仓库
  • 出现误删,需要使用git checkout branch file找回
  • 命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
    在这里插入图片描述

2.远程仓库

本地Git仓库和Github仓库之间传输是通过SSH加密

创建SSH Key

  1. ssh-keygen -t rsa -C "youremail@example.com":回车即可,无需设置密码
    • 找到.ssh目录下的id_rsaid_rsa.pub,这两个是SSH Key的密钥对
    • id_rsa是私钥
    • id_rsa.pub是公钥
  2. Github下的setting,找到SSH and GPG keys,点击New SSH Key粘贴即可
    在这里插入图片描述

在这里插入图片描述

2.1 添加远程库

本地和远程仓库同步

  1. 本地仓库下运行命令git remote add origin url,对远程库添加别名
  2. 推送到远程
    • 第一次推送git push -u origin master,本地master和远程的master分支关联起来
    • 之后可以省略,直接用git push origin master

2.2远程克隆

git clone url克隆网络库

3.分支管理

创建新的分支后,如果要处理原来的分支,需要此。

3.1 分支与管理

HEAD不是指向提交,而是指向master,而master是指向提交的
HEAD指向当前分支
过程:

  • 初始化
    在这里插入图片描述

  • 新增分支
    在这里插入图片描述

  • 切换分支,并且提交内容
    在这里插入图片描述

  • 合并分支
    在这里插入图片描述

  • 结果
    在这里插入图片描述

  1. 查看分支git branch
  2. 创建分支git branch <name>
  3. 切换分支git checkout <name>
  4. 创建+切换分支git checkout -b <name>
  5. 合并某分支到当前分支git merge <name>
  6. 删除分支git branch -d <name>

新版切换分支switch

  1. 切换分支git switch
  2. 创建并切换git switch -c dev
  3. 切换到已有分支git switch master
    Git鼓励大量使用分支

3.2 解决冲突

合并时会出现代码冲突。

  • 不同分支修改代码相同的部分,从而导致合并分支时出现冲突
  • 解决冲突,就是把合并失败的文件进行手动修复,然后再提交add + commit
    合并前:
    在这里插入图片描述

合并后:
在这里插入图片描述

  • 合并git merge <name>
  • 查看分支合并情况和分支历史:git log --graph --pretty=oneline --abbrev-commit
  • 合并分支图git log --graph

3.3 分支管理策略

合并时,默认采取Fast farword,一旦合并,看不到合并历史,删掉分支看不到分支信息

  • 禁用Fast farword,合并分支可以出现分支信息,git merge --no-ff -m "merge with no-ff" dev
  • --no-ff禁用Fast farword
  • -m <message>合并后,commit的信息
  • 查看分支历史git log --graph --pretty=oneline --abbrev-commit
  • 建议使用git merge --no-ff -m "merge with no-ff" dev

不使用Fast forward模式,merge后就像这样 :
在这里插入图片描述

团队分支管理

  • master应该非常稳定,只用来发布新版本
  • dev用来做事,意味着不稳定
  • 等到新版本发布时,把dev分支合并到master上,在master发布版本
  • 多人合作,多加分支,然后合并到dev
    团队分支脑图:
    在这里插入图片描述

3.4Bug分支cherry-pick

修复bug,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除.

  1. 假设场景A正在开发的软件
  2. 假设master分支上面发布的是A的1.0版本,dev分支上开发的是A的2.0版本
  3. 若这时用户反映 1.0版本存在漏洞,则需要从dev切换到master去修复漏洞, 这时按理应该先提交在dev分支上的工作,然后从dev分支切换到master分支去修复漏洞,但这时你在dev分支上的工作只进行了一半,还没法提交。
  4. 此时可以用git stash命令来把当前工作现场(dev分支)“储藏”起来,等以后恢复现场后继续工作。
  5. 切换到master分支,在master分支建立issue-101分支,切换到issue-101分支修复漏洞,修复完成后提交commit,然后切换到master分支上合并issue-101分支git merge --no-ff -m "merged bug fix 101" issue-101
  6. 切换回dev分支,git stash list命令看看stash内容,然后git stash pop,恢复的同时把stash内容也删了继续工作。
  7. 但这个bug也会出现在dev分支上,要修复需要把bug分支提交的修改4c805e2 fix bug 101复制过来,而不是整个master分支merge过来,有git cherry-pick 4c805e2,git会自动commit
  8. 存在git cherry-pick后,不需要在dev分支上手动再修复一次。
  9. 同样,也可以在dev上修复,然后在master上重放,但是必须要git stash,才能切换到master分支,不然文件会丢失

主要流程:

  • git stash储藏工作分区
  • git switch切换分支
  • git branch <name>创建新分支
  • git merge --no-ff -m "merged bug fix 101" issue-101修复好bug
  • git switch dev切换回去
  • git stash list查看储藏内容
  • git stash pop恢复并且删除内容
  • git cherry-pick <commit id>打上之前的漏洞补丁

注意

  1. git stash apply stash@{0}恢复储藏内容,但是不删除stash内容
  2. git stash drop删除stash内容
  3. git stash pop恢复并删除

3.5 强制删除

开发一个新特性功能,最好新建一个分支。

  • 如果要舍弃一个已经提交但是没有被合并过的分支,强行删除git branch -D <name>

3.6 多人协作

从远程clone仓库时,自动把本地master和远程master对应。

  • git remote -v查看远程仓库信息

3.6.1 推送分支

git push origin master推送到远程分支上
git push origin dev推送其他分支

区别推送
  • master:主分支,时刻与远程同步
  • dev:开发分支,需要同步
  • bug分支:只用于本地使用
  • feature:根据是否共同开发推送

3.6.2抓取分支

  • git clone默认只会克隆master分支。
    如果要在dev上开发,必须创建远程的dev分支:
  • git checkout -b dev origin/dev
  • 完成工作后推送git push origin dev
常见问题

同事同时推送了origin/dev

  • 出现冲突用git pull,在本地合并,解决冲突后,再推送
    如果没有指定本地dev和远程的origin/dev的链接:
  • 设置devorigin/dev链接:git branch --set-upstream-to=origin/dev dev
  • git pull
  • 解决冲突,再git push origin/dev

3.6.3 多人协作的工作模式

  1. git push origin <branch-name>推送自己的修改
  2. 推送失败,git pull试图合并
  3. 解决冲突,本地提交
  4. git push origin <branch-name>推送

问题

问题:A:push 文件1.txt B:push 文件1.txt(显然冲突),所以先pull,然后手工合并,假如合并过程中,A又push 文件1.txt了。等B合并完,push 文件1.txt时,又冲突掉了。感觉这情况很影响工作效率,请问git是否有对这情况有处理机制的?(SVN是有“锁”这概念的)。

答:无解,找A吵一架,所以说共同开发时,合作很重要!

3.7 Merge

指令介绍

git merge branchA branchB

  • branchB一般默认为当前branch,可以省略

远程merge

git merge origin master:将originmerge到master
git merge origin/master:将origin上的master分支merge到当前的branch

在这里插入图片描述

在这里插入图片描述

3.8 Rebase

后push的开发者不得不先pull,本地合并,然后才能push成功。多次合并后,分支变得杂乱无章。

  • 查看本地和远程的版本对比:
$ git log --graph --pretty=oneline --abbrev-commit
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello
  • 本地:582d922
  • 远程:d1be385
  • 本地比远程快分支两个

这时,如果已经有人推送了分支,先pull一下,再查看状态。加上刚才合并的提交,本地比远程分支超前3个提交。

  • git log查看
$ git log --graph --pretty=oneline --abbrev-commit
*   e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\  
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/  
* d1be385 init hello
...
$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello

使用方法

变基前:
在这里插入图片描述

变基后:
在这里插入图片描述

master分支为基,对feature分支进行变基

  • git rebase master feature:特性分支向前移植到master分支

  • 常用git rebase操作把本地开发分支移植到远端的origin/分支

  • 即为“把你的补丁变基到xxx分支的头”

  • rebase最适合的是本地分支喝远端对应跟踪分支之间的合并:

    • 除了自己开发之外,还有其他人往这个分支进行合入。
    • 每次准备提交到远端之前,先变基,这个时候基分支就是远端的追踪分支
    • git rebase origin/feature feature
  • 常用:git reabse或者git pull --rebase

  • 把分叉的提交历史“整理”成一条直线,看上去更直观。

  • 缺点是本地的分叉提交已经被修改过了。

总结

  • rebase操作可以把本地未push的分叉提交历史整理成直线;
  • rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
  • git rebase本质是将当前基分支和当前分支的差异提交获取到,然后在“基分支”最新提交点后面讲差异逐个再次提交,最后将HEAD指向最新提交点

4. 标签管理

标签就是版本库的快照,指向某个commit id的指针。

  • 分支可以移动,标签不能移动
  • tag和某个commit id绑定

4.1 创建标签

  1. 切换到需要打标签的分支上
  2. git tag <tagname> [commit id]创建一个标签,默认标签是最新提交的commit上
  3. 可以指定历史提交的commit idgit log --pretty=oneline --abbrev-commit
  4. git tag -a <tagname> -m "describe" [commit id]指定标签信息
  5. git tag查看所有标签
  6. git show <tagname>查看标签信息
注意
  • 标签总是和某个commit挂钩
  • 如果这个commit既出现在master分支,也出现在dev分支,那么在这两个分支上都可以看到这个标签

4.2 操作标签

默认标签都只存储在本地,不会推送到远程

  • git push origin <tagname>推送一个本地标签去远程库
  • git push origin --tags推送全部未推送的本地标签到远程库
  • git tag -d <tagname>删除一个本地标签
  • git push origin :refs/tags/<tagname>可以删除一个远程标签,但先从本地删除

5. 远程仓库的使用

5.1 自定义Git

配置设置

git config --global color.ui true 输出显示颜色

忽略特殊文件

  • 如果不打算提交一些特殊文件,在git工作区的根目录下创建一个特殊的文件:.gitignore
  • 在此文件里,加入要忽略的文件名,git就会自动忽略这些文件
忽略文件原则
  1. 忽略操作系统自动生成的文件,比如缩略图等
  2. 忽略编译生成的周昂见文件、可执行文件等。如果一个文件是通过另一个文件自动生成的,那么自动生成的文件就没必要放进版本库,比如java编译产生的.class文件
  3. 忽略带有敏感信息的配置文件,比如存放口令的配置文件
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini

# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build

# My configurations:
db.ini
deploy_key_rsa
  1. 提交.gitignore到git
  2. git status提醒working directory clean
注意
  • 添加忽略里声明的文件git add -f <filename>
  • 检查.gitignore规则错误的地方:git check-ignore -v <filename>
  • .gitignore里添加例外规则: !+文件名
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class

# 不排除.gitignore和App.class:
!.gitignore
!App.class

配置别名

  • git status缩减成git st: git config --global alias.st status
  • co表示checkoutgit config --global alias.co checkout
    --global参数是全局参数,全局可用
  • git reset HEAD file的缩减名git unstage <filename>git config --global alias.unstage 'reset HEAD'
  • git last显示最后一次提交信息:git config --global alias.last 'log -1'
    特殊设置
    git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

5.2 配置文件

  • --global的配置文件位置:.git/config
  • 别名:alias

5.3 配置gitlab server

步骤

  1. 安装gitsudo apt-get install git
  2. 创建新用户:sudo adduser git
  3. 创建证书登录:
    1. 收集所需要登录的用户的公钥,即id_rsa.pub文件
    2. 公钥导入/home/git/.ssh/authorized_keys文件里,一行一个
  4. 初始化/srv/sample.git的Git仓库:sudo git init --bare sample.git
    1. 服务器上的Git仓库都以.git结尾
    2. owner改为git
    3. sudo chown -R git:git sample.git
  5. 禁用shell登录:
    1. 找到/etc/passwd里的git:x:1001:1001:,,,:/home/git:/bin/bash
    2. 修改为git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
    3. 每次登录git-shell就会自动退出
  6. 克隆:git clone git@server:/srv/sample.git

管理公钥

  1. 人少:每个人的公钥收集起来放到服务器/home/git/.ssh/authorized_keys
  2. 人多:Gitosis

管理权限

  • 类似SVN进行权限管理,工具:Gitolite

迅速安装


curl https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-10.8.2-ce.0.el7.x86_64.rpm

sudo rpm -ivh /opt/gitlab-ce-10.8.2-ce.0.el7.x86_64.rpm

sudo yum install -y curl policycoreutils-python openssh-server cronie 

sudo lokkit -s http -s ssh

sudo yum install postfix

sudo service postfix start

sudo chkconfig postfix on

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

sudo EXTERNAL_URL="http://gitlab.example.com" yum -y install gitlab-ce 
服务操作
初始化

gitlab-ctl reconfigure

启动

gitlab-ctl start

停止

gitlab-ctl stop

关闭防火墙

service firewall stop

6. Git Cheat Sheet

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值