跳转至

Git

参考资料:

配置Git

一般Ubuntu系统中都预先装有git,在终端输入:

git --version

如果恰好没有安装则:

sudo apt-get install git

配置个人信息:

git config --global user.name "Your name"
git config --global user.email "email@example.com"

想要连接到GitHub,终端输入

ssh -T git@github.com

如果返回信息是:

Warning: Permanently added ‘github.com,204.232.175.90’ (RSA) to the list of known hosts. 
Permission denied (publickey).

则说明可以连接。

sudo apt-get install ssh
cd ~/.ssh
ssh-keygen -t rsa -C "email@example.com"

然后输入以下命令查看密钥:

cat id_rsa.pub

在GitHub里依次Settings -> SSH Keys -> Add SSH Key即可

在终端里输入如下命令:

ssh -T git@github.com

如果返回如下信息:

Hi "Your Name"! You’ve successfully authenticated, but GitHub does not provide shell access.

则表明添加成功。

本地使用Git

比如我们新建一个目录:

$ mkdir test
$ cd test
$ touch README.md

git status

在进行任何 Git 操作之前,都要先切换到 Git 仓库目录,也就是先要先切换到项目的文件夹目录下。比如我们在新建的test目录下输入:

$ git status
fatal: not a git repository (or any of the parent directories): .git

这个错误信息表明当前目录还不是一个git仓库。

git init

那么我们对当前目录进行初始化:

$ git init
Initialized empty Git repository in /home/kylin/Downloads/test/.git/
$ gti status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README.md

nothing added to commit but untracked files present (use "git add" to track)

初始化后默认在master分支,并提示README.mdUntracked files,即文件还没有被提交到git仓库里。

git add

系统提示可以用git add去操作想要提交的文件:

$ git add README.md
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   README.md

系统提示Changes to be committed,即README.md等待被提交,也可以用git rm --cached移除这个缓存。

git commit

利用git commit提交:

$ git commit -m "first commit"
[master (root-commit) 05d6198] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
$ git status
On branch master
nothing to commit, working tree clean

-m后面跟随的是对于本次提交的一些说明信息。

git log

输入git log查看git日志:

$ git log
commit 05d6198c33e606cf6d26cd7a22dfe40640d17f0e (HEAD -> master)
Author: zyq2652192993zyq <2652192993@qq.com>
Date:   Wed May 6 16:53:09 2020 +0800

    first commit

git log可以查看所有产生的commit记录,备注信息是first commit

git add相当于先把提交项添加到一个缓存,然后用git commit进行提交。这样是为了防止错误提交。

git branch

branch是分支的意思,分支是个很重要的概念,团队协作时每个人在各自的分支完成相应的任务,不同人之间互不影响,最后合并起来。可以通过git branch查看当前分支

$ git branch
* master

如果想要新建一个分支:

$ git branch newBranch
$ git branch
* master
  newBranch

会发现master前面有个*,表明虽然我们新建了一个分支,但是当前所在的分支还是master,新建的分支和master分支是一模一样的。

git checkout

如果想在新建的分支完成一些操作,首先需要切换到目标分支:

$ git checkout newBranch
Switched to branch 'newBranch'
$ git branch
  master
* newBranch

发现此时*newBranch前面,表明当前在newBranch分支。

如果想把新建分支并直接切换到新分支:

git checkout -b newBranch

-b是创建一个新分支newBranch,然后用checkout命令切换到新分支。

git merge

我们在新建的分支执行的操作在没有合并到master分支之前,master分支是没有任何改动的。此时需要两个步骤:

  • 首先切换到master分支
  • 将想要合并的分支合并过来:git merge newBranch
$ git checkout master
$ git merge newBranch

git branch -d

假如分支的代码已经合并到master了,那么这个新的分支就不需要了,可以用git branch -d newBranch进行删除。

$ git branch -d newBranch
Deleted branch newBranch (was 05d6198).

git branch -D

假如我们新建的分支没有合并到master,执行git branch -d会失败。如果仍然想不合并就删除分支,就需要-D命令。

$ git checkout -b newBranch1 # 新建分支并切换到分支newBranch1
Switched to a new branch 'newBranch1'
$ echo "Hello world" > README.md # 修改README.md
$ git add README.md
[newBranch1 f5d0a1d] change to README.md
 1 file changed, 1 insertion(+)
$ git commit -m "change to README.md"
On branch newBranch1
nothing to commit, working tree clean
$ git checkout master
Switched to branch 'master'
$ git branch -d newBranch1
error: The branch 'newBranch1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D newBranch1'.
$ git branch -D newBranch1
Deleted branch newBranch1 (was f5d0a1d).

git tag

git tag就是给代码标记版本

$ git checkout -b a
Switched to a new branch 'a'
$ git tag v1.0
$ git tag
v1.0

远程使用Git

SSH

git服务器一般都选择使用SSH公钥来进行授权,所以向GitHub提交代码第一步就要添加SSH key配置。

生成SSH key

我们的操作环境是在Windows下使用WSL,在终端输入ssh查看是否安装:

$ ssh
usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-E log_file] [-e escape_char]
           [-F configfile] [-I pkcs11] [-i identity_file]
           [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]
           [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]
           [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
           [user@]hostname [command]

出现以上信息表明系统已经安装了ssh,如果没有安装ssh,则可以:

$ sudo apt-get install ssh

安装好ssh后,输入ssh-keygen -t rsa,这里rsa是利用rsa算法生成密钥,接着输入三个回车(不需要输入密码),然后就会生成两个文件id_rsaid_rsa.pub,其中id_rsa是密钥,id_rsa.pub是公钥,在Linux环境下,这两个文件在~/.ssh下面。

$ ls ~/.ssh
authorized_keys  id_dsa  id_dsa.pub  id_rsa  id_rsa.pub  known_hosts

接下来需要将id_rsa.pub内容添加到GitHub上,这样本地id_rsa密钥根GitHub的id_rsa.pub公钥配对,授权成功才可以提交代码。

GitHub上添加SSH key

在GitHub的setting选项里依次选择:

SSH and GPG keys -> New SSH key

然后把id_rsa.pub的内容添加到Key下面就可以了。

添加成功后终端输入:

$ ssh -T git@github.com
Hi zyq2652192993zyq! You've successfully authenticated, but GitHub does not provide shell access.

Push & Pull

把我们在本地修改的代码推到远程仓库使用命令push

$ git push origin master

如果想把远程仓库的代码同步到本地,使用命令pull

$ git pull origin master

提交代码

首先clone我们自己的项目,执行:

$ git clone git@github.com:zyq2652192993zyq/test.git

这里的test指在GitHub里的仓库名称。执行完成后不需要git init的操作,并且本地仓库也和远程仓库进行了关联。

如果本地已经有一个git仓库,比如本地有一个test2的仓库,需要在GitHub上新建一个test项目。

  • 首先在GitHub上新建一个test项目。
  • 第二步把本地test2仓库和GitHub上的test仓库进行关联。
$ git remote add origin git@github.com:zyq2652192993zyq/test.git

查看当前项目有哪些远程仓库使用:

$ git remote -v

在提交代码前需要设置自己的用户名和邮箱,在初始配置的时候已经设置了,这里就不再设置了。

Git进阶

我们每次commit都会产生一条loglog里标记了提交人的姓名和邮箱,所以需要在提交前设置用户名和邮箱。

如果某一个项目需要特定的邮箱,只需切换到项目,去掉--global参数即可。

alias

alias相当于对某些命令的“快捷键”,比如每次输入commit会很麻烦,我们可以:

$ git config --global alias.co checkout

这样co就是checkout的别名,执行git cogit checkout是一样的效果。

$ git config --global alias.cm 'commit -m "update"'

还可以利用alias来设置一些组合:

$ git config --global alias.psm 'push origin master'

可以利用alias来对git log进行简单的美化:

$ git log --graph --pretty=format:'%Cred%h%Creset -
%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
--date=relative

但是每次输入这么一长串命令太累了,所以可以用alias进行简化:

$ git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -
%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
--date=relative"

其他配置

git默认的编辑器是vi,可以换成vim

$ git config --global core.editor "vim"

开启git着色,美化:

$ git config --global color.ui true

设置显示中文文件名

$ git config --global core.quotepath false

默认在~/.gitconfig文件下,可以通过git config -l查看

diff

diff命令主要查看我们对代码做了哪些改动。

注意git diff只比较当前文件和暂存区文件差异(git add),其他用法:

# 比较两次提交之间的差异,id可以通过log信息查看
$ git diff <$id1> <$id2>
# 比较两个分支的差异
$ git diff <branch1> <branch2>

checkout

checkout除了有切换的功能,还可以执行撤销,但是只能撤销还有add进暂存区的文件。

$ git checkout filename

stash

原则上每次commit的代码应该有实际意义,如果代码写到一半,并且还没有commit,那么可以用命令stash先保存起来,用git status查看也发现当前分支很干净。

执行以下命令发现暂存区多了一条记录:

$ git stash list

还原暂存起来的代码:

$ git stash apply

然后删除在stash的记录:

$ git stash drop

上述两个动作可以进行合并:

$ git stash pop

pop会首先还原代码,然后自动删除在stash暂存的记录。

如果想清除stash所有的记录,可以使用:

$ git stash clear

merge & rebase

merge已经有合并的功能了,为什么还需要rebase

  • merge合并可以清晰的知道修改源于哪个分支
  • rebase会首先进行比较,然后按照时间进行排序,合并后更有逻辑性。
# using merge command
$ git checkout master
$ git merge newBranch
# using rebase command
$ git checkout master
$ git rebase newBranch

解决冲突

一般在开发过程中尽量避免各自开发的代码产生相互干扰,但是特殊情况下,比如A修改了一个基础库的一个类,B也修改了这个类,那么假如A首先merge,没有任何问题,但是当B进行merge的时候就会提示conflicts

Git分支管理

避免每次git push输入用户名和密码

第一步:在根目录(/home/user/)下创建文件.git-credentials

第二步:在该文件中添加信息:

https://username:password@github.com

其中usernamepassword替换为自己的账户名和密码。

第三部:执行命令:

$ git config --global credential.helper store

执行完后,在根目录下的.gitconfig中会多出:

[credential]
    helper = store

第四步:重启bash,然后接下来每次git push就不需要输入账户名和密码了。

git clone出错

在执行git clone [git link]的时候报错:

error: RPC failed; curl 18 transfer closed with outstanding read data remaining

可以有三种解决方案,第二种方案,也就是只clone最近的一个版本最有效。

  • 加大缓冲区
$ git config --global http.postBuffer 524288000 # 缓冲区大致扩充到500M
  • clone最近的一个版本
$ git clone https://github.com/[reposity].git --depth 1
  • 更换协议

clone http方式换成SSH的方式,即 https:// 改为 git://