git使用相关文档
配置ssh公私钥
git提供了基本ssh协议的git服务。需要先 github/gitlab/gerrit上配置好账户/仓库的ssh公钥。
生成sshkey命令: ssh-keygen -t rsa -C "xxx@xxx.com" 按提示完成三次回车,即可生成sshkey。默认会在 ~/.ssh里生成id_rsa 和 id_rsa.pub一对公私钥文件。
注意:这里的xxx@xxx.com 只是生成的sshkey的名称,并不约束或要求具体全名为某个邮箱。
PS: rsa有不同的算法,github使用ed25519,以上命令默认使用此算法。如果需要使用其他算法,如rsa 2048,可以加入参数 -b 2048,即ssh-keygen -b 2048 -t rsa -C "xxx@xxx.com"
将 id_rsa.pub里的内容,粘贴到 github/gitlab/gerrit上 里的 个人 - settings - ssh keys里。
git 配置
- 编辑git的个人配置文件: vim ~/.gitconfig
[user] name = xxx email = xxx@xxx.com [alias] st = status -s ci = commit l = log --oneline --decorate -12 --color ll = log --oneline --decorate --color --graph lc = log --graph --color co = checkout br = branch mg = merge --log=9999 d = difftool [color] ui = true diff = true status = true branch = true interactive = true
2. 编辑ssh的配置文件(如果本地存在多个私钥或使用私钥登陆不同的域名需要的用户名不同,则需要编辑此文件): vim ~/.ssh/config
Host gerrit.xxx.com Hostname gerrit.xxx.com Port 29418 User xxx IdentityFile ~/.ssh/id_rsa Host github.com IdentityFile ~/.ssh/id_rsa.github User git
下载工程代码到本地(含commit-msg脚本)【重要:使用Gerrit必须要有此脚本】
git clone "ssh://xxxx@gerrit.test.com:29418/project_name" && scp -p -P 29418 xxxx@gerrit.test.com:hooks/commit-msg "project_name.git/hooks/"
新建远程分支
可以在gerrit web页面上新建,注意initial version处填写被复制的分支名。这样,新建出来的分支与此分支的代码就一样了。我从本地新建分支直接推到远程,因为权限原因,报失败无法成功提交代码。
commit & push代码
Gerrit不允许用户直接push代码到分支上(特别授权用户除外),否则报错:prohibited by Gerrit。正确的做法是所有提交都push到 HEAD:refs/for/分支名。
git add 文件名/文件夹名
git commit -m "msg"
git push origin HEAD:refs/for/分支名
push后有其他修改需要追加提交,使用以下命令。这样不会产生新的commitId,而会追加到该分支最近一个commitId中,方便review代码。单纯地想写commit msg,也可以使用该命令
git commit --amend
git push origin HEAD:refs/for/分支名
配置 gerrit 提交信息
编辑.git/config,加入以下内容:
[remote "review"] url = ssh://userName@gerrit.xxxx.com:29418/projectName push = HEAD:refs/for/master%r=reviewer1@xxx.com,r=reviewer2@xxx.com
r = xxx@xxx.com,是reviewer的用户名
隐藏与恢复进度
git stash
保存当前工作进度,会把暂存区和工作区的改动保存起来。即把没有commit的内容都隐藏起来。执行完这个命令后,在运行git status
命令,就会发现当前是一个干净的工作区,没有任何改动。使用git stash save 'message...'
可以添加一些注释。
git stash list
显示保存进度的列表。也就意味着,git stash
命令可以多次执行。
git stash pop [-index][stash_id]
git stash pop
恢复最新的进度到工作区。git默认会把工作区和暂存区的改动都恢复到工作区。git stash pop --index
恢复最新的进度到工作区和暂存区。(尝试将原来暂存区的改动还恢复到暂存区)git stash pop stash@{1}
恢复指定的进度到工作区。stash_id是通过git stash list
命令得到的- 通过
git stash pop
命令恢复进度后,会删除当前进度。
git stash apply [–index] [stash_id]
除了不删除恢复的进度之外,其余和git stash pop
命令一样。
git stash drop [stash_id]
删除一个存储的进度。如果不指定stash_id,则默认删除最新的存储进度。
git stash clear
删除所有存储的进度。
查看git 状态
git status
命令用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了, 哪些没有, 哪些文件没有被Git tracked到。
执行结果举例: 领先1个提交,说明本地仅有一个commit未合并入远程分支。落后1个提交,表示远程分支有更新,需要git pull到更新到本地。
位于分支 branch_name 您的分支领先 'origin/branch_name' 共 1 个提交。 (使用 "git push" 来发布您的本地提交) 未跟踪的文件: (使用 "git add <文件>..." 以包含要提交的内容) .gitignore .idea/
合并commit https://blog.csdn.net/u013276277/article/details/82470177
具体步骤如下:
git log
查看当前分支提交情况。如本地有3个commitID,由近到远分别为commitID1, commitID2, commitID3。需要合并commitID1和commitID2。
git rebase -i commitID3
其中,-i 的参数是不需要合并的 commit 的 hash 值,这里指的是commitID3, 接着我们就进入到 vi 的编辑模式
进入vi模式后,在键盘上敲i键进入insert模式。这时候先看看这里面的东西是什么含义,
- pick 的意思是要会执行这个 commit
- squash 的意思是这个 commit 会被合并到前一个commit
所以commitID1前写squash,commitID2前写pick。
修改完成后,按esc键,冒号,输入wq进行保存。之后会继续跳转到commit message 的编辑界面,保存后退出即可。再git log看一下commit情况,发现commitID1合到了commitID2上。
可以参考文档:https://www.cnblogs.com/LinuSiyu/p/11572703.html
取消最近的commit
使用git log查看git提交日志,由近到远分别为commitD1, commitD2 想取消commitD1,并将修改amend到commitD2上。可以这样操作:
git reset --soft commitD1
git add xxx
git commit --amend commitD2
撤消提交
本地已经commit但不想提交远程,撤消单个文件
git rm -r --cache foldername
git rm --cache filename
修改本地文件后,不想再让git来控制,但这个文件之前被add commit和push过。
git rm --cache filename
git update-index --assume-unchanged filename
最后将文件加入.gitignore中。
撤消commit --amend https://segmentfault.com/a/1190000014272359
如果只 amend 了一次, 那么直接用 git reset HEAD@{1}
就可以撤销这次 amend. 如果 amend 多次, 就参考 git reflog
进行撤销.
下面以实例介绍如何就地撤销 git commit --amend
.
git reflog
git reset --soft HEAD@{n}
如果想撤销到暂存区, 就用 git reset --soft HEAD@{n}
. 也就是改动的内容被保存在缓存区,即撤销该commit,但是又不能撤销该提交包含的更改。
如果想干掉这个修改, 就用 git reset --hard HEAD@{n}
. 即改动都被丢弃,无法恢复了。
虽然在调用时加上 --hard选项可以令git reset成为一个危险的命令(译注:可能导致工作目录中所有当前进度丢失!),但本例中工作目录内的文件并不会被修改。不加选项地调用git reset并不危险——它只会修改暂存区域
git reset 表示重置当前分支。
git reset也可参考这个文档《get reset三种模式的区别》:https://www.jianshu.com/p/c2ec5f06cf1a
撤销commit中单个文件的修改
举例:a.java文件被修改了,已经commit且push到review中了。这时发现,不需要将文件中的改动推到远端。试着使用git rm --cached a.java,push到远端后发现,居然远端认为我要删除这个文件。查了下资料,发现可以这样操作:
git log a.java
git reset <commit-id> a.java
git checkout a.java
git commit --amend
git push origin <remoteBranch>
pull代码
遇到过这样一种场景。从master拉出分支branch1,开发完后push到远端进行review。这个过程中,master代码有更新,branch1上的代码需要做相应调整。我们应该如何操作呢?
首先,需要merge master到branch1中,并更新远端代码。不然review代码时,会把master里更新的内容也diff出来,显得有些乱。
然后,本地的branch1需要 git pull --rebase 远程的branch1分支。记得需要使用--rebase参数,直接使用git pull,会产生一个merge的commit,造成一次提交对应两个commit,不利于代码review。这里也体现了merge和rebase的区别。merge会将历次commit都保留下来,而rebase会将历次commit都合并起来,并且不产生新的commit。使用rebase,我们可以把自己的修改git commit --amend到自己的commitID上了,较为方便。
merge代码
提代码时遇到这样一个场景。我的本地分支merge master分支后,想把merge后的内容推到远端。发现git log里明明有master里的commit,但push提示无可以提交的内容。查了下资料,发现原来是因为没有需要手动merge的内容,git合并时fast-forward了:Git 合并两个分支时,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,叫做“快进”(fast-forward)。因为 feature 就在 master 的下游,所以直接移动了 master 的指针,master 和 feature 都指向了 C。所以git认为无需要提交的改动。
这种场景下,我们需要使用--no-ff参数。命令: git merge --no-ff feature
--no-ff参数禁止fast-forward,表示会新建一个commit,这样就可以向远端提交代码了。
rebase 和 merge的区别:https://www.cnblogs.com/LinuSiyu/p/11572739.html rebase为变基,也就是改变当前分支的基点。
cherry pick
合并分支上的某个或某几个commit。 merge是合并整个分支,即所有commit 。
强制覆盖本地代码与远程一致
git reset --hard origin/master
有时本地有过时很久的未提交代码。直接更新远程代码,可能会产生不少冲突。可以直接强制覆盖本地代码,保持与远程仓库一致。