4.6 我的 Git 使用指南 ===================== |image0| -------------- 一、Hello world --------------- 1.1 创建版本库 ~~~~~~~~~~~~~~ :: $ mkdir learngit $ cd learngit $ git init 1.2 添加提交 ~~~~~~~~~~~~ :: $ git add readme.txt $ git commit -m "版本说明" git add 的各种区别: :: git add -A // 添加所有改动 git add * // 添加新建文件和修改,但是不包括删除 git add . // 添加新建文件和修改,但是不包括删除 git add -u // 添加修改和删除,但是不包括新建文件 在 commit 前撤销 add :: git reset // 撤销单个文件的add git reset // 撤销所有文件的add add/commit 前撤销对文件的修改 :: git checkout -- README.md // 如果你误删工作区实体文件,可以通过这个命令,将master最新版本还原到工作区 1.3 删除文件 ~~~~~~~~~~~~ :: $ rm readme.txt # 删除工作区的实体文件 $ git rm readme.txt # 删除工作区和暂存区文件,commit后版本库也将删除,如果不commit,版本库未删除,那么 git checkout -- readme.txt可以将版本库恢复到工作区。 1.4 远程仓库 ~~~~~~~~~~~~ origin 并不是指得是远程的仓库,而是指得是远程仓库在本地的一个指针。 为什么是这个名字呢?仅仅是因为 git 用它做为默认名被广泛使用,一个习惯而已,你也可以叫其他名字。 对一个在本地创建的仓库,如果添加远程仓库? .. code:: shell $ git remote add [shortname] [url] # shortname是你命名的远程仓库名字,url格式如下:git@github.com:github_account/repository_name.git #注意记得先在GitHub上先新建仓库,my_repository,不然后面 push 会出错 $ git remote add learn_git git@github.com:wongbingming/my_repository.git 推送/克隆 .. code:: shell $ git push -u learn_git master #learn_git是之前命名的远程仓库名,master是你要推送到的远程仓库的分支名字 $ git push -u learn-git master:master $ git clone [github url] # 举例 $ git clone git@github.com:iswbm/test.git 更改远程仓库地址 .. code:: shell $ git remote set-url origin git@:you_repo.git upstream 和 downstream Git中的upstream和downstream的概念是相对的。 如果A库中的分支x被push到B库中的分支y,则y就是x的upstream,而x就是y的downstream。 1.5 GitHub合并至本地 ~~~~~~~~~~~~~~~~~~~~ .. code:: shell $ git merge origin/master 1.6 创建SSHkeys ~~~~~~~~~~~~~~~ .. code:: shell $ ssh-keygen -t rsa -C "youremail@example.com" 一路回车然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码 然后就会生成id_rsa和id_rsa.pub 两个文件 1. id_rsa是私钥,不能泄露 2. id_rsa.pub是公钥,可以放心告诉别人,而我们也只需要这个公钥,来连接我们GitHub。 建完成后,使用如下命令查找位置 .. code:: shell $ find / -name id_rsa.pub 二、查看状态 ------------ 2.1 文件状态 ~~~~~~~~~~~~ .. code:: shell $ git status #如果修改了文件,状态会提示你有文件被修改(但不能告诉你哪里被修改),提示你要commit $ cat readme.txt #查看实体文件的内容 $ git ls-files #查看哪些文件在版本控制下 查看当前目录下有哪些远程仓库 .. code:: shell $ git remote # 远程仓库名字 $ git remote -v # verbose的缩写,显示详细信息,包括项目url 需要注意的是,当前Git Shell在不同目录下,git remote显示的远程仓库就不同 查看提交的历史 .. code:: shell $ git log --pretty=oneline --abbrev-commit 查看不同的地方(修改) .. code:: shell $ git diff # 工作区(work dict)和暂存区(stage)的比较 $ git diff --cached # 是暂存区(stage)和分支(master)的比较 意思就是说,我们修改文件并保存实体文件,可以使用git diff查看不同之处,再确定是否add到暂存区 保存到暂存区后可以用git diff --cached查看stage暂存区和master分支的不同之处,决定是否commit $ git diff HEAD -- readme.txt # 比较工作区和master最新版本readme.txt的不同 查看某个文件的变更记录 .. code:: shell # 列出某个文件的变更记录,有 commitID $ git log -- filename # 查看具体变更了啥 $ git show # 若该次提交的文件很多,可以只查看指定文件 $ git show 或者 .. code:: shell # 相当于上面两个命令的合体 git log -p 2.2 Git日志 ~~~~~~~~~~~ .. code:: shell $ git log # 可以查看who在when修改了文件(会写出版本说明),但是这个看着眼花缭乱 $ git log --pretty=online # 这样,每行只显示一次修改,修改信息只有:commitid + 版本说明 $ git reflog # 显示所有修改的日志 $ git log --graph --all --decorate # 以可视化图的形式展示 2.3 查看修改 ~~~~~~~~~~~~ 使用 diff 进行查看 |image1| 查看两个 commit 之间的修改 .. code:: shell $ git diff commit_id1 commit_id2 $ git diff commit_id^! # 如果只想看改了哪些文件 $ git diff commit_id1 commit_id2 --stat 查看某个 commit 的改动 .. code:: shell $ git show commit_id $ git show --stat commit_id 查看两个分支之间的差异 .. code:: shell # 查看两个分支有哪些文件发生改变了 git diff stable/2.2.9 stable/2.3.0 --stat # 对比某一个文件在两个文件中的变化 git diff stable/2.2.9 stable/2.3.0 -- README.md git diff stable/2.2.9:README.md stable/2.3.0:README.md 三、状态回滚 ------------ 往下看之前,请先理解这三个Git区域: ``工作区`` -> ``暂存区(stage)`` -> ``版本库`` 3.1 撤消工作区修改 ~~~~~~~~~~~~~~~~~~ 这里分为两种情况: 1. 实体文件被修改,但还没add到暂存区 2. add到暂存区,但是实体文件又被修改 无论是哪种情况的撤消,本质都是将工作区的修改直接丢弃,并选择还原到该文件最近的一个状态。 对于第一种情况,离它最近的是版本库,所以撤消完后会还原到版本库的状态; 对于第二种情况,离它最近的是暂存区,所以撤消完后会还原到暂存区的状态。 那么如何撤消呢? .. code:: shell # 注意--之后有空格,最后加你要撤消的文件 $ git checkout -- readme.txt 3.2 撤消你的 add ~~~~~~~~~~~~~~~~ 已经修改了文件,并add到暂存区,若要撤消这个add,可以使用这个命令 .. code:: shell $ git reset HEAD readme.txt 3.3 撤消 commit ~~~~~~~~~~~~~~~ **撤消 commit,并且撤消 add,不删除工作区修改** 如下两条命令效果一样,因为 ``--mixed`` 是默认参数,它的意思是 不删除工作空间改动代码,撤销 commit,并且撤销git add . 操作。 其中 ``HEAD^`` 的意思是上一个版本,它等同于 ``HEAD~1`` ,如果你进行了 2 次 commit,想都撤回,可以使用 ``HEAD~2``\ 。 .. code:: shell $ git reset HEAD^ $ git reset --mixed HEAD^ **只撤消 commit,不撤消 add,不删除工作区修改** .. code:: shell $ git reset --soft HEAD^ **撤消 commit,撤消 add,删除工作区修改** .. code:: shell $ git reset --hard HEAD^ **若只想修改commit message** 执行如下命令,就会进入 vim 编辑器,对应修改即可 .. code:: shell $ git commit --amend 3.4 回退到特定版本 ~~~~~~~~~~~~~~~~~~ 上面都是介绍回退到上一版本,如果要回退到前几个版本,怎么整呢? **用 HEAD 指定是前几个版本** 使用 ``git reset`` ,直接回退,不生成新的提交 .. code:: shell # HEAD是当前版本 # HEAD^是上一个版本 # HEAD^^是上上个版本 # HEAD~100是前100个版本 # 回到上一个版本 $ git reset --hard HEAD^ # 若本地不小心修改或删除了很多文件,一个一个恢复太麻烦,可以这样,回到上一个版本 $ git reset --hard HEAD 使用 ``git revert``\ ,间接回退,会生成新的提交 .. code:: shell # 会生成一次新的提交,提交重新会有三次提交 $ git revert HEAD # 相反使用 reset,直接将指针指向上一次提交之前,会有 0 次提交 $ git reset HEAD **使用 commit id 回退** 如果有很多个版本,你也不想去数到底前几个版本,可以使用 commit id 精准回退,就像下面这样 .. code:: shell $ git reset --hard 04c632e244 # hard后面这一串字符是commit id(版本号),只要前面几位就ok,但是如果我们关掉git,想恢复到之前的新版本,但是不知道id了,那就要用第三种方法了 那么问题就来了,如何获取这个 commit id呢?主要有如下两种方法 .. code:: shell # 最前面那个即是 commit id,这个commit id 是短的 $ git reflog $ git log --oneline # 这里的 commit id 是长的 $ git log $ git log --pretty=online 3.5 撤消你的撤消 ~~~~~~~~~~~~~~~~ 当你对本地工作区的修改已经add并commit后,你发现你想撤消你的这些commit,但是你一不小心执行了 .. code:: shell $ git reset --hard HEAD^ 这条命令会将你的本地工作区的修改也还原到上一次commit。相当于你之前做的所有修改全部都丢失了。 而我们原本只是想撤消 commit 和 add,而不想连本地的修改也丢弃。 这时候如何补救呢? 很简单,先使用 ``git reflog`` 找到你的 reset 的 commit id |image2| 然后再次使用 ``git reset`` 指定 commit id 回到一次修改add前的状态 |image3| 3.6 回退远程提交 ~~~~~~~~~~~~~~~~ .. code:: shell # 可能需要先回退本地,再执行第二条命令,有可能不用,需要再试 $ git reset --hard commit_id # 回退一个版本 $ git push origin HEAD --force 3.7 删除版本库里的文件 ~~~~~~~~~~~~~~~~~~~~~~ .. code:: shell # 加了 --cached 就不会删除工作区的文件 $ git rm --cached file1.txt $ git commit -m "remove file1.txt" $ git push origin branch_name 四、分支管理 ------------ 4.1 新建-切换-删除分支 ~~~~~~~~~~~~~~~~~~~~~~ .. code:: shell $ git checkout -b dev # 创建dev分支,把HEAD指针切换到dev # 相当于下面两条命令 ------------------------ $ git branch dev # 新建 $ git checkout dev # 切换指针 ------------------------ $ git branch # 查看所有分支,*表示当前分支 # 合并分支:把dev合并到当前master分支(已经切换到master分支的状态下) $ git merge dev # 删除dev分支:dev不能是当前分支 # 如果dev之前和远程仓库同步过,这次要删除前如果有修改需要先同步才能修改,不然需要用-D $ git branch -d dev # 删除本地的远程分支 git branch --delete --remotes / git branch --delete --remotes origin/stable/2.2.5 git branch -dr origin/stable/2.2.5 # 直接删除远程分支 git push origin --delete stable/2.2.5 4.2 分支冲突 ~~~~~~~~~~~~ 两个分支都修改了合并冲突问题 请查阅:\ `廖雪峰:解决合并冲突问题 `__ .. code:: shell 【合并分支的见解】 1. master分支:只有a.txt,但在分支dev提交了b.txt,b.txt在master分支是没有的。这种合并是不会有问题的,合并后,master,将增加b.txt 2. 在分支dev修改了内容,切换到master,对同一文件修改同一处地方的不同内容。这时候合并,就会出现冲突,我们需要手动修改文件为我们需要的内容,然后最后提交。 4.3 合并分支 ~~~~~~~~~~~~ 请参阅:\ `廖雪峰:分支管理策略 `__ .. code:: shell $ git merge # 默认使用Fast Forward快速合并,这种不会留下合并信息 $ git merge --no-ff -m "sometext" # 由于不采用快速合并,会生成一次commit,所以需要-m 说明,这个好处可以查到合并信息 # 多个分支,暂存区是公用的。 4.4 本地分支与远程分支 ~~~~~~~~~~~~~~~~~~~~~~ :: 1. 本地分支如果和远程分支同名,push时只要写一个分支名即可 2. 如果不同名,可以使用"git push -u origin local_branch_name:remote_branch_name" 五、保存现场stash ----------------- 假如我们当前正在dev分支工作,但是master主分支有bug需要紧急修复,但是dev的工作才进行到一半,完成还需要一天,我们想在不提交的情况下,把bug修复好,改怎么做? :: # 这时候就可以用git stash,保存 # 然后切换到master修复bug,修复完成后再切换到dev $ git stash list # 查看保存的list stash@{0}: WIP on dev: 6224937 add merge $ git stash apply # 恢复但不删除stash $ git stash drop # 删除 # 如果list中有多个stash,可以选择 $ git stash apply stash@{1} #"git stash pop"(在恢复的时候,同时把stash内容也删了)==""(恢复)+""(删除stash内容) 六、标签管理 ------------ **标签的意义** 1. 标签的作用相当于commit ID 2. 区别在于commit ID是机器生成的,不便于记忆和可读性,tag是人为设定的,有特殊意义,有很强的可读性 **如何打标签** 首先切换到你要打标签的分支上,通常是master :: $ git tag v1.0 #给当前分支打上v1.0的标签 $ git tag v1.0 6a5819e #如应该在之前版本打的标签没打,可以这样补打 ------------------------------------------------------------------------------- $ git tag #显示当前分支的所有标签 $ git show v1.0 #查看v1.0的信息:commit ID,Author,Date -------------------------------------------------------------------------------- $ git tag -a v1.1 -m "version 1.1 released" 3628164 # -m 添加说明文字,-a v0.1:使用git show v1.1,有tag的信息 标签不自动push到远程,若要push,可以使用命令 .. code:: shell $ git push origin v1.0 #推送单个tag $ git push origin --tags #一次性推送所有tag 删除标签 :: 1. 本地删除 $ git tag -d v1.0 #删除标签v1.0 2. 远程删除(如果已经推送到远程,要先本地删除,再远程删除两个步骤) $ git push origin :refs/tags/v1.0 # 要查看是否远程删除了,可以上GitHub上看 七、Github 使用 --------------- 7.1 认证授权 ~~~~~~~~~~~~ 当我们刚开始使用Github的时候,如果要将仓库里的代码clone到本地,需要对这台HOST进行授权。 本地创建 SSH Keys :: ssh-keygen -t rsa -C "wongbingming@163.com" |image4| 生成的私钥 ``/c/Users/wangbm/.ssh/id_rsa``\ ,由本机电脑保存。 生成的仅钥 ``/c/Users/wangbm/.ssh/id_rsa.pub``\ ,需要在Github上添加。 在github上添加ssh keys方法如下: |image5| 添加完后,可以使用这个命令测试一下。 :: ssh -T git@github.com Hi BingmingWong! You've successfully authenticated, but GitHub does not provide shell access. 至此,我们的PC已经认证通过。 7.2 添加用户 ~~~~~~~~~~~~ 虽然我们已经认证通过,但是如果要对线上的仓库进行操作,我们肯定还需要进行登陆操作。 参过执行如下两个配置用户信息的命令 :: git config --global user.name 'BingmingWong' git config --global user.email wongbingming@163.com 配置完后我们就可以进行clone线上代码了。 |image6| 7.3 使用 SourceTree ~~~~~~~~~~~~~~~~~~~ Git 的使用全都是命令行的,由于没有那么直观,所以很容易就会误操作。 在这里,我推荐使用 SourceTree 这个Git可视化管理工具(Github出品的Github Desktop真心觉得不好用)。 可以点击这里下载:https://cn.atlassian.com/software/sourcetree 在Mac 上安装很方便,在 Windows 上可能会需要你安装 `.net Framwork 4.7.2 `__ 。 下载安装完后,进入初始界面,需要登陆一下https://bitbucket.org/(没有的话就注册一下 )。 然后你可以将你的本地仓库直接拖进来管理,也可以直接连接github。 需要注意的是,使用它需要你进行一步操作。在 7.2 章节,我在机器上生成了一对私钥和公钥,在这里需要配置一下才能正常访问和提交我们的Github仓库。 |image7| 如果想要用户名和密码登陆,可以将上面的 OpenSSH 改成 PuTTY/Plink就行了。 八、Gitlab 使用 --------------- 8.1 免密使用 ~~~~~~~~~~~~ 新建一个配置文件:\ ``/root/.gitconfig`` .. code:: ini [user] email = wangbm@163.com name = wangbm [push] default = matching [gui] recentrepo = /root/git/deployment recentrepo = /root/git/vmp2.0 [credential] helper = store 使用再次 git pull,提示你输入密码后,再次输入后,git 会给你存储下来,下次就不需要你再输入密码。 -------------- |image8| .. |image0| image:: http://image.iswbm.com/20200602135014.png .. |image1| image:: http://image.iswbm.com/20191217150942.png .. |image2| image:: http://image.iswbm.com/20191231165152.png .. |image3| image:: http://image.iswbm.com/20191231165239.png .. |image4| image:: https://i.loli.net/2018/04/15/5ad2c06e8893d.png .. |image5| image:: http://image.iswbm.com/20190511163855.png .. |image6| image:: https://i.loli.net/2018/04/15/5ad2c2a9813b9.png .. |image7| image:: http://image.iswbm.com/20190430235625.png .. |image8| image:: http://image.iswbm.com/20200607174235.png