本文从易用性的角度梳理了一些关于git相关常用的场景以及不同场景的处理方案。即使不准备面试,也可以看看,作为平时工作的参考。关于git的前世今生就不在本文做陈述,直接上干货。
git init
:创建 Git 库。git status
:查看当前仓库的状态。git show
:# 显示某次提交的内容 git show $idgit diff
:查看本次修改与上次修改的内容的区别。git add
:把现在所要添加的文件放到暂存区中。
git log -p
:查看每次详细修改内容的 diff 。git rm
:从版本库中删除文件。git reset
:从暂存区恢复到工作文件。git reset HEAD^
:恢复最近一次提交过的状态,即放弃上次提交后的所有本次修改` 。
git commit
:把 Git add 到暂存区的内容提交到代码区中。
git clone
:从远程仓库拷贝代码到本地。git branch
:查看当前的分支名称。
git branch -r
:查看远程分支。git checkout
:切换分支。git merge
:将 branch 分支合并到当前分支。git stash
:暂存。
git stash pop
:恢复最近一次的暂存。git pull
:抓取远程仓库所有分支更新并合并到本地。
git push origin master
:将本地主分支推到远程主分支。git commit
:把 Git add 到暂存区的内容提交到代码区中。
git clone
:从远程仓库拷贝代码到本地。git branch
:查看当前的分支名称。
git branch -r
:查看远程分支。git checkout
:切换分支。git merge
:将 branch 分支合并到当前分支。git stash
:暂存。
git stash pop
:恢复最近一次的暂存。git pull
:抓取远程仓库所有分支更新并合并到本地。
git push origin master
:将本地主分支推到远程主分支。只能说十个里面九个菜,还有一个是大神,虽然命令行提供了全部的功能,但是很多用 GUI 工具可以很便捷解决的问题,命令行做起来都比较麻烦。
当然并不是让大家不要去命令行,通过命令行可以对 git 的功能和原理有一个更深入的了解。
IDEA Git 插件越来越强大,很多时候,我们日常使用 Git ,更多使用它。使用起来也非常简单,就不在此陈述。
日常使用的一个图形化的 Git 增强工具,而最好用的功能就在于它集成了 GitFlow ,让开发者可以更简单、更规范的去做一些 Git 操作;
另外它还提供了更友好的 merge 界面,但是操作起来不是很顺手,因为它只支持整行删除。
Git 是分布式版本控制系统,SVN 是集中式版本控制系统。
所以,很多公司的开发团队使用 Git 作为版本管理,而产品团队使用 SVN 。
git branch xxx_dev
:创建名字为 xxx_dev
的分支。git checkout xxx_dev
:切换到名字为 xxx_dev
的分支。git push origin xxx_dev
:执行推送的操作,完成本地分支向远程分支的同步。tag ,指向一次 commit 的 id ,通常用来给分支做一个标记。
git tag -a v1.01 -m "Release version 1.01"
。git push origin --tags
。git tag
。git log --pretty=oneline tagA..tagB
。git log --pretty=oneline tagA..
。可以通过 git commit --amend
来对本次 commit 进行修改。
分支本身就像是指标或贴纸一样的东西,它指着或贴在某个 commit 上面,分支并不是目录或档桉的复制品(但在有些版控系统的确是)。
在 Git 裡,删除分支就像是你把包装盒上的贴纸撕下来,贴纸撕掉了,盒子并不会就这样跟着消失。所以,当你删除合并过的分支不会发生什么事,也不会造成档桉或目录跟着被删除的状况。
在回答这个问题之前需要先了解 Git 仓库的三个组成部分:
git commit
后的记录区。再然后,我们就可以来说一下 git add
和 git stage
了。
git stage
的原因其实比较有趣:是因为要跟 svn add
区分,两者的功能是完全不一样的,svn add 是将某个文件加入版本控制,而 git add 则是把某个文件加入暂存区。git stage
,然后把 git diff --staged
做为 git diff --cached
的相同命令。基于这个原因,我们建议使用 git stage
以及 git diff --staged
。如果你在 git add
过程中误操作,你最终会添加不想提交的文件。但是,git rm
则会把你的文件从你暂存区(索引)和文件系统(工作树)中删除,这可能不是你想要的。
换成 git reset
操作:
git reset filename # or
echo filename >> .gitingore # add it to .gitignore to avoid re-adding it
git reset
是 git add
的逆操作。Git 合并的两种方法。
git merge
,把本地代码和已经取得的远程仓库代码合并。git rebase
,是复位基底的意思。git merge
会生成一个新的节点,之前的提交会分开显示;而 git rebase
操作不会生成新的操作,将两个分支融合成一个线性的提交。
这两个命令都是把修改从一个分支集成到另一个分支上,它们只是以非常不同的方式进行。
考虑一下场景,在合并和变基前:
A <- B <- C [master] ^ \ D <- E [branch] |
在 git merge master
之后:
A <- B <- C ^ ^ \ \ D <- E <- F |
在 git rebase master
之后:
A <- B <- C <- D <- E |
使用变基时,意味着使用另一个分支作为集成修改的新基础。
git pull --rebase
,否则这些开发人员将会得到损坏的或不一致的仓库。.git
目录下的东西。首先是它们的共同点:用来撤销代码仓库中的某些更改。
然后是不同点:
1)从 commit 层面来说:
git reset
,可以将一个分支的末端指向之前的一个 commit 。然后再下次 Git 执行垃圾回收的时候,会把这个 commit 之后的 commit 都扔掉。git reset
还支持三种标记,用来标记 reset 指令影响的范围:
--mixed
:会影响到暂存区和历史记录区。也是默认选项;--soft
:只影响历史记录区;--hard
:影响工作区、暂存区和历史记录区。
注意:因为
git reset
是直接删除 commit 记录,从而会影响到其他开发人员的分支,所以不要在公共分支(比如 develop)做这个操作。
git checkout
,可以将 HEAD 移到一个新的分支,并更新工作目录。因为可能会覆盖本地的修改,所以执行这个指令之前,你需要 stash 或者 commit 暂存区和工作区的更改。git revert
,和 git reset
的目的是一样的,但是做法不同,它会以创建新的 commit 的方式来撤销 commit ,这样能保留之前的 commit 历史,比较安全。另外,同样因为可能会覆盖本地的修改,所以执行这个指令之前,你需要 stash 或者 commit 暂存区和工作区的更改。2)从文件层面来说
git reset
,只是把文件从历史记录区拿到暂存区,不影响工作区的内容,而且不支持 --mixed
、--soft
和 --hard
。git checkout
,则是把文件从历史记录拿到工作区,不影响暂存区的内容。git revert
,不支持文件层面的操作。总的来说,回答关键点:
git revert
不支持文件层面的操作。git reset
操作。git reset --hard
指令把提交理掉了,有机会救回來吗?放心,基本上东西进了 Git 就不容易消失,它們只是以一种我们肉眼看不懂的格式存放在 Git 空间裡。我们可以透過 git reflog
指令去翻一下被 reset 的那個 Commit 的编号值,然後再做一次 git reset --hard
就可以把它救回來了。
git stash
git pull
git stash pop
git reset –hard
git pull
假如你现在的分支为 main_dev
,并在这个分支上修复了一个Bug ,但是在 main_zh_test
分支也发现了同样的一个 Bug ,如果不用 copy 代码的方式,你如何把 main_dev
修复这个 Bug 提交的代码合并到 main_zh_test
分支上,请贴出你的 Git 操作指令和指令的含义?
main_dev
分支上,通过 gitlog 命令,使用 bugid 搜索提交的 commit id 。git checkout main_zh_test
命令,切换到 main_zh_test
分支。git cherry-pick commitid
将对 Bug 的修改批量移植到该分支上。git commit
,提交到本地。git push
,推送到远程仓库。如果你正在某个分支进行开发,突然被老叫去修别的问题,这时候你会怎么处理手边的工作?
git commit
,等要处理的问题解決後再回來這個分支,再 git reset
把 Commit 拆开來继续接著做。git stash
指令,先把目前的进度存在 stash 上,等任务結束后可以再使用 git stash pop
或 git stash apply
把当时的及大怒再拿出來。pull = fetch + merge
git fetch
是取回远端更新,不会对本地执行 merge 操作,不会去动你的本地的内容。而是用 ·git pull` 会更新你本地代码到服务器上对应分支的最新版本。
如果要代码库的文件完全覆盖本地版本。
fork ,是对一个仓库的克隆。克隆一个仓库允许你自由试验各种改变,而不影响原始的项目。
一般来说,fork 被用于去更改别人的项目(贡献代码给已经开源的项目)或者使用别人的项目作为你自己想法的初始开发点。
使用 fork 提出改变的一个很好的例子是漏洞修复。与其记录一个你发现的问题,不如:
- fork 这个仓库
- 进行修复
- 向这个项目的拥有者提交一个 pull requset
如果这个项目的拥有者认同你的成果,他们可能会将你的修复更新到原始的仓库中
Clone ,不是 Fork ,克隆是个对某个远程仓库的本地拷贝。克隆时,实际上是拷贝整个源存储仓库,包括所有历史记录和分支。
Branch ,是一种机制,用于处理单一存储仓库中的变更,并最终目的是用于与其他部分代码合并。
Git 服务器的选择,实际上是比较多的。
私有化部署方案
Bitbucket
注意,Gitlab 和 Bitbucket 也提供公有服务的方案。
一般情况下,大多数公司使用 GitLab 作为 Git 服务器
GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。
它拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。它还提供一个代码片段收集功能可以轻松实现代码复用,便于日后有需要的时候进行查找。