Git常用高频命令实例

(branch_name统一指代分支名称,个人根据自己的分支名称需要做替换,不能直接写"branch_name"这个字符串)

在线练习

在线练习使用Git

如何撤销Git操作

参考阅读

git多账号配置

场景:在同一台机器上配置多个Git帐号(比如:Github,Gitlab,Gitee等)

  1. 移除全局配置(可选,没有设置的可以不用移除)
# 移除全局配置账户

git config --global --unset user.name

#查看全局用户名

git config --global user.name

# 移除全局配置邮箱

git config --global --unset user.email

# 查看全局邮箱

git config --global user.email


# 移除全局密码

git config --global --unset user.password

# 查看全局密码

git config --global user.password

备注:如下,笔者实践中,没有设置全局密码,所以只进行以下操作。

# 设置全局用户和邮件

git config --global user.name "tester"
git config --global user.email "tester@test.com"

检查时可使用git config -l命令查看全局配置。

  1. 生成公私钥文件
ssh-keygen -t rsa -C username@xxx.com

参数说明:
-t 要生成的秘钥的类型
-c 用于识别这个秘钥的注释

执行命令后,会提示输入要保存key的文件路径,密码(Enter passphrase)。如果是初次设置,都可以直接回车,不输入。

但配置多个的时候,文件路径需要变化(比如我设置的test,实际上公私钥文件都是test命名开头的)。

如果还是默认回车,会提示你是否要覆盖。

gen-ssh-key

如图,新生成了 gitlabyx.pub 文件,执行 cat gitlabyx.pub,将公钥内容通过对应git平台的“SSH Keys”添加。

add-ssh-key

  1. 添加config文件

在上述~/.ssh/目录下,手动新增一个 config 文本文件,为每个账号配置一个Host节点。

主要配置项说明:

填写说明:

Host          主机别名
HostName       服务器真实地址
IdentityFile  私钥文件路径
PreferredAuthentications 认证方式
User 用户名(例如:Github/Gitlab/Gitee帐号)

config文件的内容

Host fspt    # 可以自定义,但是使用时要注意,也可以不写
HostName github.com
IdentityFile ~/.ssh/test
User git     # 这个默认会用全局设置

# gitlab
Host gitlab.eelantech.com
HostName 10.0.0.8
IdentityFile ~/.ssh/gitlabyx
PreferredAuthentications publickey  # 用ssh建议设置上
User liyanxi@eelantech.com
  1. 测试多端配置
github的账号
$ ssh -T fspt
Hi GitHub Username! You've successfully authenticated, but GitHub does not provide shell access.

gitlab的账号测试:

cd ~/test_project/
git init .
git remote add origin git@gitlab.xxxx.com:xxx/xxx.git
git add -A
git commit -m "1st commit"
git push -u origin dev

能顺利完成配置说明操作成功,如果配置了全局username,email,这是的提交者依然是全局的。

  1. 为不同项目设置不同的用户名和邮箱

找到项目所在目录下的.git/ 文件夹,进入.git/文件夹,然后执行如下命令分别设置用户名和邮箱。

git config user.name "yanxi"
git config user.email "liyanxi@eelantech.com"

然后在.git/目录下执行命令查看config文件:cat config

local_variables

发现里面多了刚才配置的用户名和邮箱信息,即成功为该项目单独设置了用户名和邮箱。

ref: 在同一台机器上配置多个Git帐号

0.git clone

最基础的命令,把仓库拉取到本地。常用下面几个语句

git clone git@xxx.com:xxx/abc.git
将abc项目拉取到当前目录,项目目录为abc

git clone git@xxx.com:xxx/abc.git abc_v2
将abc项目拉取到当前目录下的abc_v2目录,项目目录为abc_v2 (abc_v2目录下里面就是abc.git的内容)

git clone --depth=1 git@xxx.com:xxx/abc.git

--depth 用来指定克隆的深度,1表示克隆最近的一次commit。
这种方法克隆的项目只包含最近的一次commit的一个分支,体积很小。

1.git merge

合并分支

先切换的到你的主分支上,然后合并其它分支的代码。

git checkout master
git merge -m "merge branch_name" branch_name

这样就把branch_name分支的代码合并到master分支上了,且这一步的git commit 为 "merge branch_name"

自己的项目这样也无妨,但是如果多人协作开发,这样提交会把你自己开发分支时的那些commit也都提交上去,看git log的时候很不友好。 所以推荐使用git commit --squash

2.git commit --squash branch_name

在branch_name分支上的,合并多个提交为一条。

在某些情况下,我们应该优先选择使用--squash选项(比如在开源项目中提交PR一般都会要求这样操作。)

举例:将fix_ftp_upload分支上的多个commit合并为一条,然后merge fix_ftp_upload分支到develop分支。

git checkout develop
git merge --squash fix_ftp_upload
git commit -m "merge branch fix_ftp_upload"
git push origin develop

3.git commit --amend

修改刚刚未push的提交

比如: 修改git commit -m "xxx"写错了注释。可以操作如下:

git commit --amend

进入编辑窗口,可以修改刚才写作的注释,然后wq!保存并退出

4.git stash

git stash

保存当前分支上所做的修改, 用于处理已改动而未提交的工作目录状态。

> git stash

> git status
# On branch master
nothing to commit, working directory clean

git stash pop

将stash栈的第一个stash应用并移除,经常配合git stash使用

git stash list

查看暂存栈会看到此次暂存的记录

git stash list
stash@{0}: WIP on develop: 1e20335 update:PublisherInfo  (改动描述)
stash@{1}: WIP on master: 286d74f before add debug tools
stash@{2}: WIP on dev: 115f7c1 django transaction
stash@{3}: WIP on master: 230437d modify js

git stash apply

应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0}

git stash show

显示做了哪些改动,默认show第一个存储(stash@{0}),如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

git stash show stash@{3} -p  查看stash3所做的改动

git stash清理

git stash clear 删除所有缓存的stash

git stash drop stash@{$num} 移除指定的stash

git stash drop stash@{3} 

>git stash drop stash@{3}
Dropped stash@{3} (9aa8aed27765104e44110e012238e2ed345a6d2f)

5.git branch

git branch

查看当前git仓库在本地的所有分支

git branch -D BRANCH_NAME

删除本地制定的git分支,注意不能删除当前所在分支,故删除当前分支使用的分支之前需要先切换分支。

6.git remote

git remote -v

查看远程地址

7.git checkout

git checkout --track

首先记住这两个git命令:

git checkout -b branch origin/branch

git checkout --track origin/branch

其实,这两个命令具有相同的效果,使用不同名称的本地分支时会出现实际差异。具体如下:

git checkout -b mybranch origin/abranch    # 将创建本地mybranch和跟踪origin/abranch

git checkout --track origin/abranch       # 将只创建本地'abranch',而非具有不同名称的分支

e.g.git checkout --track origin/feature/insert_event_v2

更多讨论,参见此问题

8.git tag

当某一个大版本完成之后,需要打一个标签

作用: - 记录大版本 - 备份大版本代码

在本地打标签tag

git tag -a 标签名 -m '标签描述'

例:git tag -a v1.0 -m 'version 1.0'

推送标签tag到远程仓库

git push origin 标签名

例:git push origin v1.0

删除本地和远程标签

删除本地标签

git tag -d 标签名

删除远程仓库标签

git push origin --delete tag 标签名

9.git revert

提交代码以后,你突然意识到这个提交有问题,应该撤销掉,执行如下命令:

git revert HEAD

上面命令的原理是,在当前提交后面,新增一次提交,抵消掉上一次提交导致的所有变化。它不会改变过去的历史,所以是首选方式,没有任何丢失代码的风险。

git revert 命令只能抵消上一个提交,如果想抵消多个提交,必须在命令行依次指定这些提交。比如,抵消前两个提交,要像下面这样写。

$ git revert [倒数第一个提交] [倒数第二个提交]

git revert命令还有两个参数:

--no-edit:执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息。
--no-commit:只抵消暂存区和工作区的文件变化,不产生新的提交。

10.git reset

如果希望以前的提交在历史中彻底消失,而不是被抵消掉,可以使用git reset命令,丢弃掉某个提交之后的所有提交。

git reset的原理: 让最新提交的指针回到以前某个时点,该时点之后的提交都从历史中消失

11.git rm

如果不小心把一个文件添加到暂存区,可以用下面的命令撤销。

git rm --cached [filename]

上面的命令不影响已经提交的内容。

12.撤销当前分支的变化

# 新建一个 feature 分支,指向当前最新的提交
# 注意,这时依然停留在当前分支
$ git branch feature

# 切换到这几次提交之前的状态
$ git reset --hard [当前分支此前的最后一次提交]

# 切换到 feature 分支
$ git checkout feature

上面的操作等于是撤销当前分支的变化,将这些变化放到一个新建的分支。(然后切换到另一个分支,merge feature分支上的后面几次提交的内容。)

13.git cherry-pick

git cherry-pick命令的作用,就是将指定的提交(commit)应用于其他分支。

# 现在将 feature分支的提交f 应用到 master分支。
# 先切换到 master 分支
$ git checkout master

# git cherry-pick 操作
$ git cherry-pick f

上面的操作完成以后,代码库就变成了下面的样子。

a - b - c - d - f   Master
     \
       e - f - g    Feature

ref: git cherry-pick 教程

14.git rebase -i

代码变更比较频繁,有时候想让前几次提交的合并为一次提交,这里可以使用git rebase -i 命令来完成

rebase为变基
git rebase -i 命令可以压缩合并多次提交
格式:git rebase -i [startpoint] [endpoint]

其中-i的意思是–interactive,即弹出交互式的界面让用户编辑完成合并操作,

// 合并从当前head到15f745b(commit id)
$ git rebase -i 15f745b

// 合并最近的两次提交
$ git rebase -i HEAD~2

ref:git rebase -i合并多次提交

15.git blame

git blame 显示文件的每一行最后修改的版本和作者

//显示aaa/file.txt文件第11行和12行的修改记录
git blame -L 11,12 aaa/file.txt

-L 11,12 含义是该文件的第11行和12行的修改记录

16.git remote操作

一般参考新建的git仓库可以看到提示。

本地仓库新增 remote repo

git remote add origin http://10.0.0.110/xxx/yyy.git
git push -u origin master

删除远端origin仓库绑定

git remote remove origin

从旧git repo迁移到新git repo

git remote rename origin old-origin
git remote add origin http://10.0.0.110/xxx/yyy.git
git push -u origin --all
git push -u origin --tags

如果是本地某分支要和远端某分支挂钩,可以这样设置

# If you wish to set tracking information for this branch you can do so with:

git branch --set-upstream-to=<remote>/<branch> dev

e.g.:
git branch --set-upstream-to=origin/dev dev

github同步源仓库代码

在github上fork了一个仓库后,自己的master分支为fork后的分支。 如果要同步原作者的仓库,可以在远端增加 upstream 分支,分支源设置为 源代码作者的仓库,然后定期操作pull 和 merge,或者提交PR。

git remote add origin https://github.com/TesterCC/sec-dev-in-action-src.git
git remote add upstream https://github.com/netxfly/sec-dev-in-action-src.git

服务器上的 Git - 生成 SSH 公钥

ref: https://git-scm.com/book/zh/v2/%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E7%9A%84-Git-%E7%94%9F%E6%88%90-SSH-%E5%85%AC%E9%92%A5

$ ssh-keygen -o   # 没有特别需求的化,可以一路回车

$ cd ~/.ssh
$ ls
authorized_keys2  id_rsa       known_hosts
config            id_rsa.pub

cat ~/.ssh/id_rsa.pub    # 里面的文本就是ssh key公钥

Git Fork项目后,向开源项目提交PR流程

1. 在github页面上, 点击fork按钮, 将B的项目拷贝一份到A自己的代码仓库中。
即:A为你自己的仓库, B为你fork的开源仓库。

2. 克隆A自己的代码仓库到本地.
$ git clone https://github.com/A/A.git

3. 将B的项目作为最新代码的参考标准(upstream 是上游仓库的别名,别名随意命名)
$ git remote add upstream https://github.com/B/B.git

4. 在本地更改代码(增删查等操作)

5. 暂存已经编辑的目录和文件.
$ git add .
$ git stash

6. 拉取B仓库的新代码
$ git fetch upstream

7. 将B新的部分合并到A的代码仓库中, 使A的代码仓库变成最新的代码.
$ git rebase upstream/master origin/master

8. 查看分支,确保在自己的本地分支上
$ git branch

9. 如果不在本地分支,则执行 git checkout master ,如果在则忽略此步骤

10. 将刚刚暂存的代码合并到现在最新的代码中.
$ git stash apply stash@{0}

11. 本地提交代码.
$ git add .
$ git commit -m 提交代码的注释信息"

12. 将代码推送到A的github仓库
$ git push -u origin/master

13.在A的github仓库页面上,点击pull request向B发起PR请求

14.当B仓库管理者通过你的PR请求,你的PR将会被合并到B的主分支上

以上是第一次进行fork、克隆代码、创建关联、修改代码提交等操作;
当再次本地修改代码提交时,执行步骤6-11即可。

同步开源项目最新源码到自己的开发分支

git remote -v  # 一般设置开源项目源码在upstream分支
git fetch upstream  # 从upstream仓库垃取最新的更新 # 把upstream仓库的更新拉取到本地了,但不强制合并代码
git checkout mater  # 切换到本地master分支,也可以是其他非master分支
git merge upstream/master  # 将upstream/master分支合并到本地master分支上
git push origin master     # 将合并后的本地master推送到远端仓库master分支,这时 upstream/master 的最新代码就同步到 origin/master了

git fetch 和 git pull 的区别

  • git fetch 是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。

  • git pull 是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。

其他

之前大佬教我用-i来做squash。 
中间态的若干次提交均写上 WIP: *****
然后做完一个功能, 把 WIP: *** squash掉。  
用 git rebase -i

P.S.: WIP(work in progress)

常见错误处理

git bash报错Error: Could not fork child process: There are no available terminals (-1).

打开win的cmd或者powershell,执行如下命令:

(base) PS C:\Users\xx> tasklist | findstr "git-bash"
git-bash.exe                 18476 Console                    1      5,796 K
(base) PS C:\Users\xx> taskkill /pid 18476 -t -f
成功: 已终止 PID 22436 (属于 PID 18476 子进程)的进程。
成功: 已终止 PID 18476 (属于 PID 16332 子进程)的进程。
(base) PS C:\Users\xx>

如果这样kill后还是不能正常启动git bash,那么建议重启。