Github 会用 git 应该也多多少少知道一些吧。
要是任性只会用 Github 客户端 ʕʘ̅͜ʘ̅ʔ ?告辞
参考连接/书籍
话说 Svn 与 Git 的区别
廖雪峰-Git 教程
对比 Git 与 SVN,这篇讲的很易懂
彻底搞懂 Git-Rebase
《Git 高手之路》
Git & Svn
最明显的差异是 Git 是分布式的,SVN 是集中式的
举一个最常见的例子。把代码 po 到 GitHub 上,是先在本地编辑,再扔到 GitHub 上。
如果共同维护一份代码,那么每个用户也都是这样的。每个用户都会在本地一份自己的代码。
而使用 SVN 的话,必须联网才能使用才能正常工作。
虽然 Git 也有自己的集中式服务器,但是更倾向于分布式的开发上手难度
个人觉得 Git 远难于 SVN。
Git 的指令多,常见的有 clone / add / commit / status / log / fetch / pull / push / rebase / branc / checkout 等,很多指定还有很多的选项。
SVN 的话我记得当时是必须先 update,再 commit(但是在 windows 上 SVN 真的是傻瓜式操作。存储方式
Git 按元数据(?)方式存储,而 SVN 按照文件存储。branch
SVN 无本地 branch (?因为又看到网路上的文献说其实有,但是也没有深入的说,所以保留意见
Git 有本地 branch,且可以有多个。
SVN 的 branch 很昂贵,是拷贝的目录,而 Git 的 branch 指针指向某次提交,也就使得 Git 的分支切换非常迅速。
Git 基础指令
就不管 SVN 了哈,一个是因为平时就是 Git 用的多,另一个是因为很多公司都用的 Git
之前建立了一个 next 项目的流程,可以看这里 -> 关于新建 nextJs 项目
上面的项目建立流程是 GitHub 上新建 repository -> git clone 到本地 -> npm init (没有使用 git init) -> git add -> git commit -> git push
git config
其实在进行项目之前,需要先对 git 环境进行一些配置。
1 | $ git config [--global] user.name "Your Name" |
-l 选项。可以列举查看所有的 git 配置。
–unset 选项。可以删除已经配置好的内容。
git init
npm(yarn) init 会生成一个带项目信息的 package.json 文件。
而 git init 会生成一个隐藏的 .git 目录, Git 把所有的修订信息都放在 .git 目录里。
git add / git rm / git mv
git add <file> 命令把文件加入到仓库里。
<file> 可是一个 "." (小数点) ,表示把(有变动的)当前目录及子目录中的文件都添加到版本库里。
add 还只能算是提交,并没有真正的加入到仓库,add 的文件 Git 会暂存,最终在 git commit 之后正式(和别的 add 提交上来的文件一起)提交到版本库里。
git rm 和 git add 相反,命令用于删除文件,不过也和 add 类似,不会立刻从仓库里删除文件,需要等 commit 才会真的实现。
git mv 给仓库文件重命名。
git commit
请一定要带上 -m 选项,如下
1 | git commit -m "add: add something" |
-m 选项之后跟一串描述性字符串,用于描述本次提交的说明,最好输入有意义的内容,这样就能从历史记录里方便地找到改动记录。
因为往往是多人维护一份代码,加上描述性质的语言,对于别人和以后的自己都能有效的复现当时的情景。
当然并不是强制的(之前实习的时候,就没有这个习惯…后来和同事沟通之后就一直有加了
需要注意的是,在上一次 git commit 之后,所有 git add 的文件都会在本次 git commit 中提交到版本库。
git status
其实 git status 用的会很多。
用于查看 git 状态,会显示哪些文件有变动,并提示你 git add,或者 git checkout – <file> 来撤销更新。还会显示哪些文件已经 add 了,等待 commit 。若没有文件有变动也会提示干净的工作区。
git diff
git diff <file>
用于查看某个文件的变化。
如果是提交到 GitHub 上的话,个人感觉 GitHub 上会更清晰一些。
但是也是差不多的,就是会显示某个文件某个地方更改前/后的内容。
git log
一般来说,用到 git log 说明出事了。hhh
可以查看 git 提交记录,会显示 commit 的一串内部识别码,提交作者以及提交时间。
git reflog
这个指令会显示 git 指令记录。
git show
git show <code>
这个<code>就是 git log 里的 commit 的那串识别码。
会显示某个 commit 的详细信息。包括提交作者、时间、识别码、以及 diff。
git reset –hard commit_id
虽然有 –soft / –mixed 两个其他的选项。
但是好像通常只用 –hard 。
commit_id 就是 git log 里的那个 commit 的识别码。
用于撤销 commit (或者说版本回退
git checkout
git checkout <file> 可以丢弃工作区的修改(未 git add),已经在缓存区(已 git add)的需要使用 git reset HEAD <file>
git checkout <branch_name>切换到 branch_name 这个分支
Git 提交
上面的都是基础的指令。但是 git 作为分布式管理系统,总会有一个远程的仓库需要维护。
git remote
指令用于关联本地仓库以及 GitHub(或者其他)上的远程仓库。
1 | $ git remote add origin git@github.com:yourGithubName/yourRepositoryName.git |
git push
关联后,使用命令 git push -u origin master 第一次推送 master 分支的所有内容;此后,每次本地提交后,只要有必要,就可以使用命令 git push origin master 推送最新修改; – 廖雪峰
但是我的习惯是
1 | $ git push --set-upstream origin master |
git clone
git clone <url>
克隆一个远程库
Git 支持 HTTPS,但是通过 ssh 支持原生 git 协议会更快。
Git 分支
分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习 Git 的时候,另一个你正在另一个平行宇宙里努力学习 SVN。如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了 Git 又学会了 SVN! – 廖雪峰
草
其实上面有一些指令也涉及分支管理。应该只有 checkout
创建与合并分支
文章里的图很好的解释了分支的作用和实现。
git branch
git branch 会列出所有的分支,并在当前分支名字前添加一个*号
git -d branch <branch_name> 删除名为 branch_name 分支
git -D branch <branch_name> 删除名为 branch_name 分支
-d 和 -D 区别在于 -D 是用于删除未经合并的分支的。
git branch <branch_name> 新建名为 branch_name 的分支
git checkout
其实 git checkout 也可以用于创建分支
1 | // 新建分支并前往 |
git switch
可能是就是用来解决 checkout 又能撤销更改又能切换分支的问题才新出的一个指令(瞎说的
但是确实是比较新的指令。
功能也确实就是用于切换分支。
git switch -c <branch_name> 新建并切换至新的分支
git switch <branch_name> 切换到名为 branch_name 的分支
git stash
用于把当前工作现场"储藏"起来,等以后恢复现场后继续工作。
在 git stash 之后 git status 会发现工作区是干净的。
git stash list 查看被存储的 stash 列表
git stash apply <stash_name> 用于恢复某个指定的 stash,恢复之后于 stash list 里依旧存在
git stash drop <branch_name> 用户删除某个 stash
git stash pop <branch_name> 用于恢复并删除某个 stash
git cherry-pick
用于解决一个特殊情况。
本来在开发由 master 衍生的分支 dev 时,master 里有一个 bug 需要紧急处理。
所以把 dev 用 git stash 存储了。
修好了 master 之后提交了新的代码,恢复了 dev 之后,dev 里 bug 依旧存在。
但是又不能直接 merge master 给 dev。
git cherry-pick <commit_id> 就能把提交的内容添加到 dev 里。准确的说
Git 自动给 dev 分支做了一次提交,注意这次提交的 commit 是 1d4b803,它并不同于 master 的 4c805e2,因为这两个 commit 只是改动相同,但确实是两个不同的 commit。用 git cherry-pick,我们就不需要在 dev 分支上手动再把修 bug 的过程重复一遍。
git pull
用于跟新本地代码。
出现 git push 失败,说明远程分支比本地分支更新,所以现需要 git pull 一下。
git pull 有冲突先于本地修正,再提交。
如果提示 no tracking information 则本地分支与远程分支没有建立连接。可以使用 git push 里提到的 –set-upstream 选项。
git merge & git rebase
git merge 用于合并指定的分支到当前所在的分支。
每次 merge 都会自动创建一个新的 commit,如果合并的时候遇到冲突,则只须要解决冲突后重新提交即可。但是每次 merge 都会有一个 commit,分支会很混乱。
如果 rebase 合并出现了冲突
- 解决冲突
- git add
- git rebase –continue
但是对于 rebase 争议很大,在确保没有别的人在使用需要进行 git rebase 的分之前,不要使用 git rebase。
也就是never use it on public branches