Git常用高频命令实例
(branch_name统一指代分支名称,个人根据自己的分支名称需要做替换,不能直接写"branch_name"这个字符串)
在线练习
参考阅读
git多账号配置
场景:在同一台机器上配置多个Git帐号(比如:Github,Gitlab,Gitee等)
- 移除全局配置(可选,没有设置的可以不用移除)
# 移除全局配置账户
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
命令查看全局配置。
- 生成公私钥文件
ssh-keygen -t rsa -C username@xxx.com
参数说明:
-t 要生成的秘钥的类型
-c 用于识别这个秘钥的注释
执行命令后,会提示输入要保存key的文件路径,密码(Enter passphrase)。如果是初次设置,都可以直接回车,不输入。
但配置多个的时候,文件路径需要变化(比如我设置的test,实际上公私钥文件都是test命名开头的)。
如果还是默认回车,会提示你是否要覆盖。
如图,新生成了 gitlabyx.pub
文件,执行 cat gitlabyx.pub
,将公钥内容通过对应git平台的“SSH Keys”添加。
- 添加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
- 测试多端配置
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,这是的提交者依然是全局的。
- 为不同项目设置不同的用户名和邮箱
找到项目所在目录下的.git/
文件夹,进入.git/文件夹,然后执行如下命令分别设置用户名和邮箱。
git config user.name "yanxi"
git config user.email "liyanxi@eelantech.com"
然后在.git/
目录下执行命令查看config文件:cat config
发现里面多了刚才配置的用户名和邮箱信息,即成功为该项目单独设置了用户名和邮箱。
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
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,那么建议重启。