git常用命令

理论

Git 是一个分布式版本管理系统,是为了更好地管理Linux内核开发而创立的。

Git可以在任何时间点,把文档的状态作为更新记录保存起来。因此可以把编辑过的文档复原到以前的状态,也可以显示编辑前后的内容差异。

管理历史记录的数据库

数据库 (Repository) 是记录文件或目录状态的地方,存储着内容修改的历史记录。在数据库的管理下,把文件和目录修改的历史记录放在对应的目录下。

远程数据库:配有专用的服务器,为了多人共享而建立的数据库。

本地数据库:为了方便用户个人使用,在自己的机器上配置的数据库。

提交

若要把文件或目录的添加和变更保存到数据库,就需要进行提交。

执行提交后,数据库中会生成上次提交的状态与当前状态的差异记录(也被称为revision)。

提交是以时间顺序排列状态被保存到数据库中的。凭借该提交和最新的文件状态,就可以知道过去的修改记录以及内容。

每次提交系统会自动生成没有重复的40位英文数字的 hash 值用来命名本次提交。

工作树和索引

在Git管理下,大家实际操作的目录被称为工作树。

在数据库和工作树之间有索引,索引是为了向数据库提交作准备的区域。

Git在执行提交的时候,不是直接将工作树的状态保存到数据库,而是将设置在中间索引区域的状态保存到数据库。因此,要提交文件,首先需要把文件加入到索引区域中。

所以,凭借中间的索引,可以避免工作树中不必要的文件提交,还可以将文件修改内容的一部分加入索引区域并提交。

实战

git bash中的命令行是linux操作模式。

查找git命令手册:

$ git help <verb>
$ git <verb> --help
$ man git-<verb>

如查找config命令手册,执行git help config

git 配置

1. 本地创建ssh key

在命令行中输入ssh-keygen -t rsa -C "your_email@youremail.com",确认路径和输入密码,进入.ssh文件夹中可以看到id_ras(私钥)和id_ras.pub(公钥),复制公钥中的key配置到git远程仓库,或在命令行中输入cd ~/.ssh进入.ssh文件夹中,再输入cat id_rsa查看私钥,输入cat id_rsa.pub查看公钥。

2. 与远程仓库的连接

初始化git之后连接,git remote add origin git@github.com:Datura35422/vueDemo.git

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

删除远程仓库:git remote remove <name>

3. 验证与远程仓库连接

在命令行中输入如ssh -T git@github.com进行验证与github远程仓库的连接,如果命令行中返回You've successfully authenticated, but GitHub does not provide shell access表示验证成功,注意:每个git仓库的验证成功信息不同。

本地已存在仓库建立与远程仓库联系,从远程仓库拉取代码,git pull origin master --allow-unrelated-histories

将新的分支推送到远程仓库中,git push origin new_branch

4. 全局配置

全局配置username:git config --global user.name "your name"

全局配置email:git config --global user.email "youremail@email.com"

全局配置文本编辑器:git默认编辑器是Vim,如果想配置不同的文本编辑器,如Emacs可以配置git config --global core.editor emacs

查看所有配置项:git config --list,如果有重复变量名,git会使用每个变量的最后一个配置。

查看某一项配置:如查看user.name配置,git config user.name

配置别名:git config --global alias.st status

git 基本操作

1. 克隆远程仓库代码 git clone

git clone git@github.com:michaelliao/gitskills.git

Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快

克隆远程仓库就不需要初始化本地仓库

克隆远程仓库的某个分支git clone -b dev git@github.com:michaelliao/gitskills.git

2. 拉取远程仓库代码 git pull

git pull

3. 初始化本地仓库 git init

git init

4. 将工作区代码提交到暂存区 git add

提交工作区所有修改后的文件:git add .

提交工作区具体的某个文件:git add <filename>

提交工作区某个文件夹:git add 文件夹

提交所有被删除和修改的文件到数据暂存区: git add -ugit add –update

提交所有被删除、被替换、被修改和新增的文件到数据暂存区: git add -A git add -all

*只有将工作区中的文件添加到暂存区之后才能提交到远程仓库或本地分支

5. 查看区别 git diff

查看工作区与版本库中最新版本的区别:git diff HEAD -- <filename>

查看文件详细区别:git diff <filename>, 按Q退出

6. 撤销修改git checkout -- <filename>

撤销工作区的修改,会用最近一次commit或add的文件来覆盖当前修改过的文件。如果修改已经commit到暂存区,则需要进行版本回退。

*如果命令中没有--则是切换到其他分支

git checkout 命令也可以从历史提交(或暂存区域)中拷贝文件到工作目录。当给定某个文件名(或 -p 选项,或同时使用)时,git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如,git checkout HEAD~ foo.c会将提交节点HEAD~(即当前提交节点的父节点)中的foo.c复制到工作目录并且加到暂存区域中。(如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。)注意当前分支不会发生变化。

7. 将暂存区代码提交到分支 git commit

然后git commit提交更改,将缓存区的所有内容提交到当前分支。

其中,git commit -m 'xxxx'写提交备注

如果出现权限问题和403错误,就是远程仓库没有授权,请查看远程仓库的配置。

如果想要更改一次提交,可以使用 git commit --amend 命令。git 会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。

8. 删除文件 git rm

删除版本库中的文件:git rm <filename>

不删除物理文件,仅将该文件从缓存中删除:git rm --cached

如果在工作区误删了文件,可以使用git checkout <filename>恢复文件

9. 查看历史记录 git log

简化历史记录: git log --pretty=oneline

树形结构查看历史记录:git log --oneline --graph --decorate --all

10. 查看命令历史 git reflog

从中获知未来版本的版本号并进行穿梭。

记录每一次HEAD指针版本指向问题。

11.版本回退 git reset

将暂存区修改回退到工作区:git reset HEAD <filename>,如果修改已经添加至暂存区,可以使用git reset,将暂存区的版本回退,重新放回工作区。

回退当前版本:git reset --hard HEAD

回退上一个版本:git reset --hard HEAD^

回退上上个版本:git reset --hard HEAD^^

回退指定版本:git reset --hard headname,其中headname可以在git log中查看到版本号。版本号(哈希值)可以不用写全。

git reset --mixed:默认方式,版本库中回退到某个版本,工作区保留源码。

git reset --soft:回退到某个版本,只回退了 commit 的信息,不会恢复到 index file 一级,如果需要提交则 commit。

git reset --hard:彻底回退到某个版本,本地源码也会变为上一个版本的内容。

回退之后想要修改代码,需要强制推代码上去覆盖远程仓库 history:git push -f

12. tag标签 git tag

版本标签,对某一个时间点上的版本打上标签。

列出已有的标签:git tag

查看一系列的标签:git tag -l 'v1.4.2.*'

新建轻量级标签:git tag v1.4(指向特定提交对象的引用)

新建含附注的标签:git tag -a v1.4 -m '备注'(存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用GPG来签署或验证)

查看相应标签的版本信息:git show v1.4

签署标签:git tag -s v1.4 -m 'my signed 1.4 tag'(自己的私钥,还可以用 GPG 来签署标签)

验证标签:git tag -v v1.4(会调用 GPG 来验证签名,没有公钥会报错)

后期加注标签:git tag -a v1.2 提交历史哈希值(使用git log --pretty=oneline查看提交历史,哈希值不用写全)

提交标签:git push origin v1.4

提交所有新增标签:git push origin --tags

删除标签:git tag -d v1.4

删除远程标签:需要先删除本地标签,git push origin :refs/tags/v1.4

13. 备份当前工作内容 git stash

git stash:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。

git stash save [message] :备份当前的工作区内容且设置备注。

git stash pop:从Git栈中读取最近一次保存的内容,恢复工作区的相关内容并删除stash中的内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。

显示Git栈内的所有备份:git stash list,可以利用这个列表来决定从那个地方恢复。

清空Git栈:git stash clear

恢复现场:git stash apply,需要用git stash drop删除stash中的内容。

删除stash中的内容:git stash drop

多次保存工作现场后,恢复指定的工作现场,git stash apply stash@{0}

14. 改写提交 git cherry-pick

cherry-pick 命令”复制”一个提交节点并在当前分支做一次完全一样的新提交。

参考链接: https://backlog.com/git-tutorial/cn/stepup/stepup7_4.html

15. 合并命令 git rebase

衍合是合并命令的另一种选择。合并把两个父分支合并进行一次提交,提交历史不是线性的。衍合在当前分支上重演另一个分支的历史,提交历史是线性的。 本质上,这是线性化的自动的 cherry-pick

git rebase -i HEAD~~:合并最近的两次提交,合并后进行提交。

fast-forward 合并

git rebase 分支名:和 merge 时的操作相同,如果有冲突需要修改冲突,冲突修改后会 history 指针为最新的提交。

git rebase --continue:修改冲突后的提交不是使用commit命令,而是执行rebase命令指定 –continue选项。若要取消rebase,指定 –abort选项。

16. 取消过去的提交 git revert

git revert HEAD:取消最新的一次提交,可以把 HEAD 改为提交的哈希值。

git 分支操作

1. 创建分支 dev

创建并切换分支: git checkout -b dev

创建分支: git branch dev,在需要创建的分支上创建子分支。

在本地上创建与远程分支对应的分支:git checkout -b <分支名> origin/<分支名>git checkout -t origin/<分支名>

本地分支与远程分支进行连接: git branch --set-upstream-to=origin/<branch> <branch>

创建分支注意不要和标签名发生冲突,否则会存在一对多的情况,最后只能删除分支或者标签,同名标签和分支不能共存。

2. 切换分支

切换分支:git checkout 分支名 (可以在未创建与远程分支对应分支情况下切换到该分支并拉取代码)

3. 查看分支

查看本地分支和当前分支 :git branch

查看远程和本地分支: git branch -a

查看远程分支:git branch -r

查看已删除分支情况:git remote show origin

4. 合并分支

合并指定分支到当前分支:git merge <分支名>

5. 删除分支

删除分支:git branch -d <分支名>

强行删除分支:git branch -D <分支名>

删除远程分支:git push origin --delete <分支名>

删除远程不存在的分支:git remote prune origin

删除分支的远程追踪:git branch -r -d origin/分支名

6. 分支冲突

在主分支上必须手动解决冲突之后再提交

查看分支冲突部分:git status

查看分支合并情况: git log --graph --petty=online --abbrev-commit

查看分支合并图:git log --graph

7. 合并远程分支

先将需要合并的远程分支拉取到本地,然后进行合并,如果有冲突需要解决冲突后提交。

推送到远程分支:git push origin master

将新分支推送到远程仓库:git push --set-upstream origin <分支名>

8.重命名分支

重命名分支: git branch -m <分支名>git branch -m <旧分支名> <新分支名>

异常

1. git pull 时出现冲突

错误提示:error: Your local changes to the following files would be overwritten by merge

方法1:如果你想保留刚才本地修改的代码,并把git服务器上的代码pull到本地(本地刚才修改的代码将会被暂时封存起来)

git stash // 保存当前工作区内容
git pull origin master // 拉取远程仓库master分支
git stash pop // 恢复工作区内容

方法2:如果你想完全地覆盖本地的代码,只保留服务器端代码,则直接回退到上一个版本,再进行pull

git reset --hard // 版本回退
git pull orgin master // 拉取远程仓库master分支
2.推送异常

错误提示error: failed to push some refs to xxx

大致意思:本地和远程的文件应该合并后才能上传本地的新文件

解决方法:先更新再提交,git pull -> git push

如果git pull出现错误:Pull is not possible because you have unmerged files.

本地的pushmerge会形成MERGE-HEAD(FETCH-HEAD), HEAD(PUSH-HEAD)这样的引用。HEAD代表本地最近成功push后形成的引用。MERGE-HEAD表示成功pull后形成的引用。可以通过MERGE-HEAD或者HEAD来实现类型与svn revet的效果。

解决方法:

1.pull会使用git merge导致冲突,需要将冲突的文件resolvegit add -u, git commit之后才能成功pull

2.如果想放弃本地的文件修改,将本地的冲突文件冲掉,不仅需要resetMERGE-HEAD或者HEAD,还需要--hard。没有后面的hard,不会冲掉本地工作区。只会冲掉stage区。可以使用git reset --hard FETCH_HEADFETCH_HEAD表示上一次成功git pull之后形成的commit点。然后git pull
注意:

git merge会形成MERGE-HEAD(FETCH-HEAD)git push会形成HEAD这样的引用。HEAD代表本地最近成功push后形成的引用。

错误提示fatal: refusing to merge unrelated histories

大致意思:拒绝合并不相关的历史。因本地仓库和远程仓库是两个独立的仓库,所以要强制合并成一个仓库。

解决方法: git pull origin master --allow-unrelated-histories

学习链接

猴子都能懂的GIT入门

GIT奇技淫巧英文版原文