本文整理自工做多年以来遇到的全部 Git 问题汇总,以前都是遗忘的时候去看一遍操做,此次从新整理了一下,发出来方便你们收藏以及须要的时候查找答案。html
通常代码提交流程为:工做区 -> git status
查看状态 -> git add .
将全部修改加入暂存区-> git commit -m "提交描述"
将代码提交到 本地仓库 -> git push
将本地仓库代码更新到 远程仓库前端
当你改乱了工做区某个文件的内容,想直接丢弃工做区的修改时,用命令git checkout -- file
。git
// 丢弃工做区的修改 git checkout -- <文件名> 复制代码
当你不但改乱了工做区某个文件的内容,还 git add
添加到了暂存区时,想丢弃修改,分两步,第一步用命令 git reset HEAD <file>
,就回到了场景1,第二步按场景1操做。github
// 把暂存区的修改撤销掉(unstage),从新放回工做区。 git reset HEAD <文件名> 复制代码
更改 commit 信息缓存
git commit --amend -m“新提交消息”
复制代码
commit 时,遗漏提交部分更新,有两种解决方案:bash
方案一:再次 commitmarkdown
git commit -m“提交消息”
复制代码
此时,git 上会出现两次 commitapp
方案二:遗漏文件提交到以前 commit 上dom
git add missed-file // missed-file 为遗漏提交文件 git commit --amend --no-edit 复制代码
--no-edit
表示提交消息不会更改,在 git 上仅为一次提交ssh
删除指定的 commit
// 修改版本库,保留暂存区,保留工做区 // 将版本库软回退1个版本,软回退表示将本地版本库的头指针所有重置到指定版本,且将此次提交以后的全部变动都移动到暂存区。 git reset --soft HEAD~1 // 修改版本库,修改暂存区,修改工做区 //将版本库回退1个版本,不只仅是将本地版本库的头指针所有重置到指定版本,也会重置暂存区,而且会将工做区代码也回退到这个版本 git reset --hard HEAD~1 // git版本回退,回退到特定的commit_id版本,能够经过git log查看提交历史,以便肯定要回退到哪一个版本(commit 以后的即为ID); git reset --hard commit_id 复制代码
撤销 某次操做,这次操做以前和以后的commit和history都会保留,而且把此次撤销
做为一次最新的提交
// 撤销前一次 commit git revert HEAD // 撤销前前一次 commit git revert HEAD^ // (好比:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)撤销指定的版本,撤销也会做为一次提交进行保存。 git revert commit 复制代码
git revert
是提交一个新的版本,将须要revert
的版本的内容再反向修改回去, 版本会递增,不影响以前提交的内容
git revert
和 git reset
的区别git revert
是用一次新的commit来回滚以前的commit,git reset
是直接删除指定的commit。git revert
是用一次逆向的commit“中和”以前的提交,所以往后合并老的branch时,致使这部分改变不会再次出现,可是git reset
是之间把某些commit在某个branch上删除,于是和老的branch再次merge时,这些被回滚的commit应该还会被引入。git reset
是把HEAD向后移动了一下,而git revert
是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,可以抵消要被revert的内容。git clone 地址
git branch 分支名
git branch
git branch -a
git checkout 分支名
(通常修改未提交则没法切换,大小写问题常常会有,可强制切换 git checkout 分支名 -f
非必须慎用)git push <远程仓库> <本地分支>:<远程分支>
将某个远程主机的更新,所有/分支 取回本地(此时之更新了Repository)它取回的代码对你本地的开发代码没有影响,如需完全更新需合并或使用git pull
拉取远程主机某分支的更新,再与本地的指定分支合并(至关与fetch加上了合并分支功能的操做)
将本地分支的更新,推送到远程主机,其命令格式与git pull
类似
git clone -b 分支名仓库地址
git checkout -b serverfix origin/serverfix
git merge hotfix
:(将 hotfix 分支合并到当前分支)git merge origin/serverfix
git branch -d hotfix
:(删除本地 hotfix 分支)git push origin --delete serverfix
git push origin newName
;git branch branchName
:(建立名为 branchName 的本地分支)git checkout branchName
:(切换到 branchName 分支)git checkout -b branchName
:(至关于以上两条命令的合并)git branch
git branch -a
git branch -m oldName newName
git branch -m oldName newName
git branch --set-upstream-to origin/newName
在团队协做过程当中,假设你和你的同伴在本地中分别有各自的新提交,而你的同伴先于你 push
了代码到远程分支上,因此你必须先执行 git pull
来获取同伴的提交,而后才能push
本身的提交到远程分支。
而按照 Git 的默认策略,若是远程分支和本地分支之间的提交线图有分叉的话(即不是 fast-forwarded),Git 会执行一次 merge
操做,所以产生一次没意义的提交记录,从而形成了像上图那样的混乱。
其实在 pull 操做的时候,,使用 git pull --rebase
选项便可很好地解决上述问题。 加上 --rebase
参数的做用是,提交线图有分叉的话,Git 会 rebase 策略来代替默认的 merge 策略。
假设提交线图在执行 pull 前是这样的:
A---B---C remotes/origin/master
/
D---E---F---G master
复制代码
若是是执行 git pull
后,提交线图会变成这样:
A---B---C remotes/origin/master
/ \
D---E---F---G---H master
复制代码
结果多出了 H
这个不必的提交记录。若是是执行 git pull --rebase
的话,提交线图就会变成这样:
remotes/origin/master | D---E---A---B---C---F'---G' master 复制代码
F
G
两个提交经过 rebase
方式从新拼接在 C
以后,多余的分叉去掉了,目的达到。
大多数时候,使用 git pull --rebase
是为了使提交线图更好看,从而方便 code review。
不过,若是你对使用 git 还不是十分熟练的话,个人建议是 git pull --rebase
多练习几回以后再使用,由于 rebase 在 git 中,算得上是『危险行为』。
另外,还需注意的是,使用 git pull --rebase
比直接 pull 容易致使冲突的产生,若是预期冲突比较多的话,建议仍是直接 pull。
注意:
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
上述的 git pull --rebase
策略目的是修整提交线图,使其造成一条直线,而即将要用到的 git merge --no-ff <branch-name>
策略恰恰是反行其道,刻意地弄出提交线图分叉出来。
假设你在本地准备合并两个分支,而恰好这两个分支是 fast-forwarded 的,那么直接合并后你获得一个直线的提交线图,固然这样没什么坏处,但若是你想更清晰地告诉你同伴:这一系列的提交都是为了实现同一个目的,那么你能够刻意地将此次提交内容弄成一次提交线图分叉。
执行 git merge --no-ff <branch-name>
的结果大概会是这样的:
中间的分叉线路图很清晰的显示这些提交都是为了实现 complete adjusting user domains and tags
每每个人习惯是,在合并分支以前(假设要在本地将 feature 分支合并到 dev 分支),会先检查 feature 分支是否『部分落后』于远程 dev 分支:
git checkout dev git pull # 更新 dev 分支 git log feature..dev 复制代码
若是没有输出任何提交信息的话,即表示 feature 对于 dev 分支是 up-to-date 的。若是有输出的话而立刻执行了 git merge --no-ff
的话,提交线图会变成这样:
因此这时在合并前,一般我会先执行:
git checkout feature
git rebase dev
复制代码
这样就能够将 feature 从新拼接到更新了的 dev 以后,而后就能够合并了,最终获得一个干净舒服的提交线图。
再次提醒:像以前提到的,rebase 是『危险行为』,建议你足够熟悉 git 时才这么作,不然的话是得不偿失啊。
使用 git pull --rebase
和 git merge --no-ff
其实和直接使用 git pull
git merge
获得的代码应该是同样。
使用 git pull --rebase
主要是为是将提交约线图平坦化,而 git merge --no-ff
则是刻意制造分叉。
$ cd ~/.ssh $ ls id_rsa id_rsa.pub known_hosts 复制代码
其中 id_rsa 是私钥,id_rsa.pub 是公钥。
git config --list // 查看是否设置了user.name与user.email,没有的话,去设置 // 设置全局的user.name与user.email git config --global user.name "XX" git config --global user.email "XX" 复制代码
ssh-keygen -t rsa -C "email"
)$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/schacon/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/schacon/.ssh/id_rsa. Your public key has been saved in /Users/schacon/.ssh/id_rsa.pub. The key fingerprint is: 复制代码
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== schacon@agadorlaptop.local
复制代码
git stash
可用来暂存当前正在进行的工做,好比想 pull 最新代码又不想 commit , 或者另为了修改一个紧急的 bug ,先 stash,使返回到本身上一个 commit,,改完 bug 以后再 stash pop , 继续原来的工做;
git stash
;git stash list
;git stash pop
;git stash apply stash@{1}
;Filename too long warning: Clone succeeded, but checkout failed.
git config --system core.longpaths true 复制代码
git config user.name
git config user.email
复制代码
git config --global user.name "username" git config --global user.email "email" 复制代码
git rm -r --cached . git add . git commit -m ".gitignore is now working” 复制代码
一、配置remote,指向原始仓库
git remote add upstream https://github.com/InterviewMap/InterviewMap.git
复制代码
二、上游仓库获取到分支,及相关的提交信息,它们将被保存在本地的 upstream/master 分支
git fetch upstream # remote: Counting objects: 75, done. # remote: Compressing objects: 100% (53/53), done. # remote: Total 62 (delta 27), reused 44 (delta 9) # Unpacking objects: 100% (62/62), done. # From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY # * [new branch] master -> upstream/master 复制代码
三、切换到本地的 master 分支
git checkout master # Switched to branch 'master' 复制代码
四、把 upstream/master 分支合并到本地的 master 分支,本地的 master 分支便跟上游仓库保持同步了,而且没有丢失本地的修改。
git merge upstream/master # Updating a422352..5fdff0f # Fast-forward # README | 9 ------- # README.md | 7 ++++++ # 2 files changed, 7 insertions(+), 9 deletions(-) # delete mode 100644 README # create mode 100644 README.md 复制代码
五、上传到本身的远程仓库中
git push
复制代码
本文参考了 洁癖者用 Git:pull --rebase 和 merge --no-ff
想看更过系列文章,点击前往 github 博客主页
走在最后,欢迎关注:前端瓶子君,每日更新