分布式版本控制系统
- 分布式:不止服务端,每个客户端本地也存在代码仓的完整镜像。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。
- origin 代表云端仓库
文件本地状态
- 未跟踪 untracked
- 已提交(无修改) unmodified 数据已经安全的保存在本地数据库中。
- 已修改 modified 表示修改了文件,但还没保存到本地数据库中。
- 已暂存 staged 表示对一个已修改文件的当前版本做了标记,使之包含在下次commit中。
工作区域:Git 仓库、工作目录以及暂存区域。
- 在工作目录中修改文件。
- 暂存文件(
git add .
),将文件的快照放入暂存区域(位于.git
目录中)。 - 提交更新(
git commit -m "描述"
),将暂存区域的所有文件快照存储到本地 Git 仓库的当前分支(位于.git
目录中的另一位置)。
版本回退
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,版本回退只是改变了指针的指向
- 当你想直接丢弃工作区的修改时,用命令
git checkout -- <file>
或git checkout -- .
丢弃更改(恢复到该文件上一次git add
或git commit
的状态),用git clean -df
命令清空所有新增的(未追踪的)文件/目录。 - 当你想丢弃已经添加到暂存区(git add)的修改时,分两步,先用命令
git reset HEAD <file>
或git reset HEAD .
回到场景1(不会影响文件内容),再按场景1操作。 - 当你想丢弃已经提交到本地版本库(git commit)的修改,使用
git reset --hard HEAD^
重置到上一次提交,或git reset --hard HEAD~100
重置到100次前的提交,或git reset --hard 某版本号至少前5位
重置当前到某指定版本。- 当你想舍弃掉某一个版本的提交,但是不影响这一版本和当前版本中间其他版本时,使用
git revert 版本号
- 当你想舍弃掉某一个版本的提交,但是不影响这一版本和当前版本中间其他版本时,使用
- 当你想回滚到之前某个版本并提交到远端时,需要结合使用
git reset --hard
和git push -f
- 其中
git reset
指令用于改变HEAD指针的指向-
reset --hard
会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容与新HEAD完全一致(没有commit的修改会被全部擦掉)。 -
reset --soft
保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区 -
reset --mixed
或不加参数:保留工作目录,并清空暂存区
-
- 其中
git revert
指令用于新创建一次commit提交,内容和指定版本完全相反,但不会改变commit历史
常用本地指令
- git config ([key])
查看配置 - git help
帮助 - git init
初始化git配置文件 - git status (-s) (--short)
查看当前状态(以及需要进行下一步或撤回的操作提示) - git diff 文件名
查看未暂存文件比起上次暂存有哪些修改 - git log (--pretty=oneline)
查看本时间线上的历史提交记录(时间、描述、版本号等),不包括被重置所舍弃的版本,按Q退出 - git reflog
查看时间线上所有提交(commit)、重置(reset)记录,以便于返回未来
创建新项目的两种方式
- 本地创建项目后同步到远程
在文件夹中git init
将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件
若是在已经存在文件的文件夹中执行git init
,则还需要进行以下操作
git add .
git commit -m 'initial project version'
git remote add origin [XXXXXX.git]//用于关联远程仓库
//如提示已关联过其他仓库,则需要先git remote rm origin进行移除
git push -u/--set-upstream origin master
其中git push -u/--set-upstream origin master
相当于git push origin master
+ git branch -u/--set-upstream-to=origin/master
,提交本地分支到目标远程分支(没有则新建),并关联该远程分支,下次提交只需要git push
即可。
- 克隆现有的仓库到本地
git clone [url] ([newName])
- linux系统需要使用
git clone https://username:password@github.com/XXX.git
一次完整的git提交
- 建立或克隆一个git仓库,并将其或者在其基础上创建工作目录
- 在工作目录中添加或修改文件
- 将文件的修改添加至暂存区中
git add .
- 将暂存区的文件commit至git仓库
git commit -m [description]
也可以直接使用git commit -a -m [description]
跳过步骤3(但是只监听修改,不监听新增) - 推送至远程
git pull
+git push
远程仓库 (origin - 克隆的仓库服务器的默认名)
- 生成SSH KEY:
ssh-keygen -t rsa -C "邮箱地址"
- 用户主目录里找到
.ssh
目录其中id_rsa.pub
即公钥,用于填入github的setting中
git fetch ([shortname/url])
将所有数据拉取到你的本地仓库 - 它并不会自动合并或修改当前的工作。git pull
抓取当前追踪的远程分支,并合并到当前分支。-
git push
将当前分支推送到已关联的远程分支-
git push (-u/--set-upstream) origin 本地分支名
将指定分支推送到同名远程分支(没有则新建),如带-u或--set-upstream则还会关联到该远程分支 -
git push origin 本地分支名:远程分支名
将本地分支推送到指定远程分支(没有则新建) -
git push -f/--force
危险,强制推送,推送后会舍弃当前本地版本对应的线上版本 之后的所有版本,其他合作者pull的时候会发生当前分支merge到当前分支
-
git remote (-v)
查看远端仓库信息git remote show origin
查看远端仓库信息及本地追踪的分支情况git remote add <remote-name> <url>
添加绑定远程仓库git remote rm <remote-name>
删除绑定远程仓库
分支
git的分支本质上只是对指针的操纵
-
git branch
查看本地分支列表-
git branch -a
所有分支 -
git branch -r
远端分支
-
-
git branch [name]
从当前版本新建分支-
git branch [name] 指定版本号至少前5位
从指定版本处新建分支
-
-
git branch -d 本地分支名
删除本地分支-
git branch -r -d origin/远端分支名
删除远端分支 -
git push origin -d 远端分支名
删除远端分支
-
-
git checkout (-b) [name] (origin/<branch-name>)
切换分支
-b
表示新建并切换到该分支
origin/[远端分支名]
表示从远端拉取该分支作为本地新分支 -
git checkout 指定版本号至少前5位
检出指定版本 -
git merge [name]
把本地目标分支合并到本地当前分支
发生的冲突会出现如下区段,由=======
分隔,修改后再次使用git add
即可
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
-
git merge --abort
放弃本次合并(在合并分支出现冲突时可以执行该命令) -
git branch -u/--set-upstream-to origin/<branch-name> <branch-name>
指定本地分支与远端分支关联
拉取远端新分支的两种方法
git checkout -b 本地分支名 origin/远端分支名
-
git fetch origin 本地分支名:远程分支名
+git checkout 本地分支名
操作合并
git cherry-pick <某次commit编号>
在另一分支上做了某次提交后,不想合并整个分支,只是将该次提交的修改也对当前分支生效,则使用以上指令即可
分支合并
- 将从当前HEAD点所在位置创建的分支dev,合并到当前分支master,称为
Fast-forward
,直接将HEAD指向dev最终点即可
也可以主动禁用Fast-forward
模式以在merge时生成一个新的commit
git merge --no-ff -m "描述" <分支名>
- 待合并的两个分支间分别做了提交,可能会产生冲突
git merge [name]
后手动修改文件,重新git add .
+git commit -m "描述"
即可解决
团队合作
建议master上只存在正式版本,开发提交都只提交到dev分支,多人合作时都从dev分支上创建与合并自己的分支
commit描述规范
修改commit
-
git commit --amend
用于修改上一次未push的git commit -m "XXX"
内容
bug分支
当本地有些修改不想提交,但又需要做一些新的修改并提交或切换分支,可使用git stash
暂时将当前分支的本地修改隐藏,此时可以进行其他修改并提交/切换分支等。当其他修改提交完毕后切换回原本分支,并使用git stash pop
或git stash apply
找回被隐藏的本地修改。(此时可能会发生冲突,类似merge时通过git add .
+git commit -m "描述"
解决冲突即可)
-
git stash (save "XXXX")
stash修改(并添加描述) -
git stash show (stash@{编号})
查看一次stash的详细内容 -
git stash list
查看stash列表 -
git stash pop (stash@{编号})
恢复一次被stash的修改并将其从list删除 -
git stash apply (stash@{编号})
恢复到指定位置的stash修改且不从list删除 -
git stash drop (stash@{编号})
删除list中指定内容 -
git stash clear
删除所有stash
不配置(stash@{编号})
时默认为上一次
变基
git rebase
操作可以把本地未push的分叉提交历史整理成直线,通常用于在push前整理本地分支结构。
( git rebase
会把当前分支里的每个提交(commit
)取消掉,并且把它们临时保存为补丁(patch),然后把当前分支更新到最新的目标分支,最后把保存的这些补丁应用回当前分支上)
即在git commit
+git pull
之后,先git rebase
,再git push
通常,对上游分支merge下游分支,对下游分支rebase上游分支
注意,只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。否则可能会导致其他人在该分支上做的改动丢失。人民群众会仇恨🌚你,你的朋友和家人也会嘲笑🌚你,唾弃🌚你。
配置.gitignore
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
创建.gitignore文件,如下
# no .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in the build/ directory
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory
doc/**/*.pdf
将已track的文件加入.gitignore后不生效的问题
git rm -r --cached .
git add .
git commit -m 'update .gitignore'
git rm --cached -r 文件名
Linux下配置git记住账号密码
vim ~/.gitconfig
修改配置文件,添加下面这一行。
[credential]
helper = store