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 <file> // 撤销单个文件的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 用它做为默认名被广泛使用,一个习惯而已,你也可以叫其他名字。

对一个在本地创建的仓库,如果添加远程仓库?

$ 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

推送/克隆

$ 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

更改远程仓库地址

$ git  remote set-url origin git@<new_server>:you_repo.git

upstream 和 downstream

Git中的upstream和downstream的概念是相对的。

如果A库中的分支x被push到B库中的分支y,则y就是x的upstream,而x就是y的downstream。

1.5 GitHub合并至本地

$ git merge origin/master

1.6 创建SSHkeys

$ ssh-keygen -t rsa -C "youremail@example.com"

一路回车然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码

然后就会生成id_rsa和id_rsa.pub 两个文件

  1. id_rsa是私钥,不能泄露

  2. id_rsa.pub是公钥,可以放心告诉别人,而我们也只需要这个公钥,来连接我们GitHub。

建完成后,使用如下命令查找位置

$ find / -name id_rsa.pub

二、查看状态

2.1 文件状态

$ git status #如果修改了文件,状态会提示你有文件被修改(但不能告诉你哪里被修改),提示你要commit
$ cat readme.txt #查看实体文件的内容
$ git ls-files #查看哪些文件在版本控制下

查看当前目录下有哪些远程仓库

$ git remote     # 远程仓库名字
$ git remote -v  # verbose的缩写,显示详细信息,包括项目url
需要注意的是,当前Git Shell在不同目录下,git remote显示的远程仓库就不同

查看提交的历史

$ git log --pretty=oneline --abbrev-commit

查看不同的地方(修改)

$ 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的不同

查看某个文件的变更记录

# 列出某个文件的变更记录,有 commitID
$ git log -- filename <filename>

# 查看具体变更了啥
$ git show <commitID>

# 若该次提交的文件很多,可以只查看指定文件
$ git show <commitID> <filename>

或者

# 相当于上面两个命令的合体
git log -p <filename>

2.2 Git日志

$ git log # 可以查看who在when修改了文件(会写出版本说明),但是这个看着眼花缭乱
$ git log --pretty=online # 这样,每行只显示一次修改,修改信息只有:commitid + 版本说明

$ git reflog # 显示所有修改的日志

$ git log --graph --all --decorate # 以可视化图的形式展示

2.3 查看修改

使用 diff 进行查看

image1

查看两个 commit 之间的修改

$ git diff commit_id1 commit_id2
$ git diff commit_id^!

# 如果只想看改了哪些文件
$ git diff commit_id1 commit_id2 --stat

查看某个 commit 的改动

$ git show commit_id
$ git show --stat commit_id

查看两个分支之间的差异

# 查看两个分支有哪些文件发生改变了
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到暂存区,但是实体文件又被修改

无论是哪种情况的撤消,本质都是将工作区的修改直接丢弃,并选择还原到该文件最近的一个状态。

对于第一种情况,离它最近的是版本库,所以撤消完后会还原到版本库的状态;

对于第二种情况,离它最近的是暂存区,所以撤消完后会还原到暂存区的状态。

那么如何撤消呢?

# 注意--之后有空格,最后加你要撤消的文件
$ git checkout -- readme.txt

3.2 撤消你的 add

已经修改了文件,并add到暂存区,若要撤消这个add,可以使用这个命令

$ git reset HEAD readme.txt

3.3 撤消 commit

撤消 commit,并且撤消 add,不删除工作区修改

如下两条命令效果一样,因为 --mixed 是默认参数,它的意思是 不删除工作空间改动代码,撤销 commit,并且撤销git add . 操作。

其中 HEAD^ 的意思是上一个版本,它等同于 HEAD~1 ,如果你进行了 2 次 commit,想都撤回,可以使用 HEAD~2

$ git reset HEAD^
$ git reset --mixed HEAD^

只撤消 commit,不撤消 add,不删除工作区修改

$ git reset --soft HEAD^

撤消 commit,撤消 add,删除工作区修改

$ git reset --hard HEAD^

若只想修改commit message

执行如下命令,就会进入 vim 编辑器,对应修改即可

$ git commit --amend

3.4 回退到特定版本

上面都是介绍回退到上一版本,如果要回退到前几个版本,怎么整呢?

用 HEAD 指定是前几个版本

使用 git reset ,直接回退,不生成新的提交

# HEAD是当前版本
# HEAD^是上一个版本
# HEAD^^是上上个版本
# HEAD~100是前100个版本

# 回到上一个版本
$ git reset --hard HEAD^

# 若本地不小心修改或删除了很多文件,一个一个恢复太麻烦,可以这样,回到上一个版本
$ git reset --hard HEAD

使用 git revert,间接回退,会生成新的提交

# 会生成一次新的提交,提交重新会有三次提交
$ git revert HEAD

# 相反使用 reset,直接将指针指向上一次提交之前,会有 0 次提交
$ git reset HEAD

使用 commit id 回退

如果有很多个版本,你也不想去数到底前几个版本,可以使用 commit id 精准回退,就像下面这样

$ git reset --hard 04c632e244
# hard后面这一串字符是commit id(版本号),只要前面几位就ok,但是如果我们关掉git,想恢复到之前的新版本,但是不知道id了,那就要用第三种方法了

那么问题就来了,如何获取这个 commit id呢?主要有如下两种方法

# 最前面那个即是 commit id,这个commit id 是短的
$ git reflog
$ git log --oneline

# 这里的 commit id 是长的
$ git log
$ git log --pretty=online

3.5 撤消你的撤消

当你对本地工作区的修改已经add并commit后,你发现你想撤消你的这些commit,但是你一不小心执行了

$ git reset --hard HEAD^

这条命令会将你的本地工作区的修改也还原到上一次commit。相当于你之前做的所有修改全部都丢失了。

而我们原本只是想撤消 commit 和 add,而不想连本地的修改也丢弃。

这时候如何补救呢?

很简单,先使用 git reflog 找到你的 reset 的 commit id

image2

然后再次使用 git reset 指定 commit id 回到一次修改add前的状态

image3

3.6 回退远程提交

# 可能需要先回退本地,再执行第二条命令,有可能不用,需要再试
$ git reset --hard commit_id

# 回退一个版本
$ git push origin HEAD --force

3.7 删除版本库里的文件

# 加了 --cached 就不会删除工作区的文件
$ git rm --cached file1.txt

$ git commit -m "remove file1.txt"

$ git push origin branch_name

四、分支管理

4.1 新建-切换-删除分支

$ 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 <remote>/<branch>
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 分支冲突

两个分支都修改了合并冲突问题

请查阅:廖雪峰:解决合并冲突问题

【合并分支的见解】
1. master分支:只有a.txt,但在分支dev提交了b.txt,b.txt在master分支是没有的。这种合并是不会有问题的,合并后,master,将增加b.txt
2. 在分支dev修改了内容,切换到master,对同一文件修改同一处地方的不同内容。这时候合并,就会出现冲突,我们需要手动修改文件为我们需要的内容,然后最后提交。

4.3 合并分支

请参阅:廖雪峰:分支管理策略

$ 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,可以使用命令

$ 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

[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