Git使用中遇到的需求与解决方案记录, 不定期更新。
关键概念
origin
origin
是remote组中的默认成员, 在git clone
时自动创建, 其值为远程repo的url(url以.git
结尾)。
git remote
git remote
是管理远程repo的指令, 当每一个项目独立成repo的情况下似乎不需要常使用该指令1。以下罗列可能的使用场景:
- 检查远程repo与本地的差异
git remote [-v | --verbose] update
该指令将比对所有remote组中的远程repo各个branch与本地repo相应branch的差异, 一般对个人(现阶段的我)而言, remote组中只有一个成员, 即origin
。
- 查看远程repo的全部信息
git remote -v
该指令将罗列出当前git环境下所有的远程repo信息, 以<remote_name, url>
对的形式显示, 一般而言即显示类似如下内容:
origin https://github.com/zouyu4524/RL-market.git (fetch)
origin https://github.com/zouyu4524/RL-market.git (push)
常用操作
在Commit前撤销已add的修改
git reset <file>
或者如下
git reset
撤销所有的已add但未commit的修改。
注: 如果repo还没有任何的commit, 也可以通过如下的命令撤销2
git rm [-r] --cached <added_file_to_undo>
其中-r
是可选项, 表示递归式操作, 当需要撤回的文件包含文件夹时需要设置该选项。
原理在于git ret
是将HEAD
撤销至上一次commit状态, 而若还没有任何的commit, 则HEAD
无法解析。其中2给出了很有趣的解释。
在Push前撤销已commit的修改
git reset <commit_id>
将HEAD
指针☞回commit_id
所标识的commit, 而查找相应的commit id可以通过git log <-no.>
完成。其中no.
为commit的编号, 从新到旧递增, 当前的commit编号为1, 所以可以通过
git log -2
查看目标commit, 可以进一步比对commit内容确认。明确commit id后, 执行git reset <commit_id>
即可。
注: 以上操作将完全撤销至上一次commit后的状态, 但不会撤回已经修改的代码。
创建新的Branch
Branch管理原则3:
In your github fork, you need to keep your master branch clean, by clean I mean without any changes, like that you can create at any time a branch from your master. Each time that you want to commit a bug or a feature, you need to create a branch for it, which will be a copy of your master branch.
将远程的repo(origin/master)同步至本地
git pull
然后, 以此创建新的branch
git checkout -b [name_of_new_branch]
将新的branch推送至远程repo
git push -u origin [name_of_new_branch]
在新创建的branch上进行修改, 所有的commit在该branch上开展, 直至达到阶段性的进展再考虑将其同步至master branch。
在新的branch上commit前务必确认当前处于新的branch, 如下命令查看当前branch
git branch --list
当前branch将会用*
标注。
如果当前branch中的修改到达一个阶段, 可以将其合并至master branch中, 操作如下
git checkout master
git merge origin/[name_of_new_branch]
首先切换回master branch, 再执行merge
命令, 将修改发生的branch合并至master branch中。
修改branch名称
修改本地的branch名称, 首先定位到需要修改名称的branch, 然后4
git branch -m new_name
删除旧名称的branch并将新名称推送至远程repo
git push origin :old_name new_name
为本地的branch重新创建上传的通道
git push origin -u new_name
删除branch
git push --delete <remote_name> <branch_name>
git branch -d <branch_name>
第一条删除远程的分支, 第二条删除本地分支5。
git免密push
- 添加SSH密钥6
可以首先通过ls ~/.ssh/
查看当前系统中是否存在SSH密钥, 如果显示没有以.pub
为后缀的文件, 则还没有SSH。
- 通过以下命令创建SSH密钥:
ssh-keygen -t rsa -C "any comments"
顺次会提示确认密钥存放地址, 设置查看密钥的密码/确认密码, 可以按照默认流程按三次回车则生成的密钥将存放于~/.ssh
目录下, 且无需密码查看。其中-t
是制定加密方式, 一般用rsa
, -C
用于添加注释。
- 更改
remote
url为git
格式
默认情况下, 从github的远程repo克隆时会提供https
的地址, 在这种情况下, 即便在Github的Settings/SSH keys中添加本机的秘钥也仍然需要每次push时提供账户和密码7。实际上需要通过git
的链接克隆就不会有这个问题了。如果当前的本机repo已经是通过https
地址克隆而来, 那么可以修改remote地址为git
格式即可, 如下:
git remote set-url origin git@github.com:USERNAME/REPOSITORY.git
保存进度
某些情况下需要暂时存储部分修改, 而优先改动并生效其他修改: 例如正在编辑一篇博客文章, 而博客结构需要即时做出调整, 此时, 可以首先将编辑中的博客文章推至进度, 而优先修改博客结构相关代码。实现此需求可以用到stash
指令。示例如下:
git stash push -m "message"
以上命令会将当前所有已产生的修改全部推至进度, 并打上”message”信息; 此后再执行git status
可以获得一个“干净”的工作区。但是以上并非适用所有的情形, 更多的时候可能是同时进行了多个不同目的的修改, 例如: 既有博客内容相关的修改, 又有博客结构相关的修改, 此时需要摘出需要暂存的改动, 可以通过--patch
参数(简写为-p
)对照逐条改动决定是否需要加入进度。用例如下:
git stash push -p -m "message"
git将会逐条显示改动, 并提示针对当前改动如何选择, 如下:
Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]?
其中各个字母的含义如下8:
y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
g - select a hunk to go to
/ - search for a hunk matching the given regex
e - manually edit the current hunk
? - print help
常用的选择即: y
, n
, 分别表示将当前改动加入/不加入进度。
注意到, 较早的教程中经常提及另一个命令实现以上需求, 即: git stash save -p "message"
。在较新版本的git中已建议弃用该方式, 两者的差别在于: git stash push
可以指定路径以更好的控制哪些文件需要添加至进度, 而git stash save
不具备该功能9。此外, git stash save
接收一个预留的参数位, 以接收”message”, 而git stash push
需要通过-m
指定, 相比之下, git stash push
与git commit
类似, 指令上具有更好的一致性。
从进度恢复
以上给出了选择部分修改保存至进度的方式, 相应地, 以下给出从进度恢复的方式:
git stash pop
对于简单的项目, 进度一般至多存放一次修改, 那么使用以上命令就可以实现需求, 以上面的例子而言: 在完成了博客结构相关代码的修改后, 现在需要继续博客文章的写作, 上述命令即可将进度中的修改恢复至工作区; 如果有多个进度, 也可通过git stash list
查看进度, 确认要恢复的进度id
, 并通过git stash pop stash@{id}
恢复10; 更多的用法可以参考这里。
-
git remote --help
↩ -
Stash only one file out of multiple files that have changed with Git? ↩