
Git 流程图
![]()
# 配置全局用户 ! [7 m; M! K$ L L $ git config --global user.name "用户名"9 n6 C! v1 P7 [; p! R: a H $ git config --global user.email "git账号" # 配置别名 $ git config --global alias.co checkout2 v% k }: D+ E* @ $ git config --global alias.ss status $ git config --global alias.cm commit $ git config --global alias.br branch: A, ^9 r8 N" C/ A( E% U/ `( t $ git config --global alias.rg reflog8 D: @7 Y- V- `6 ~0 n# V # 这里只是美化 log 的输出,实际使用时可以在 git lg 后面加命令参数,如:git lg -10 显示最近10条提交 $ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" # 删除全局配置, e$ N1 p4 Z: ^, I5 P9 p $ git config --global --unset alias.xxx $ git config --global --unset user.xxx; n( [( E' ]" w 查看 Git 信息 # 查看系统配置4 {5 U' W! ^/ i$ t! r9 }3 { : e$ v9 d c- B+ w $ git config --list # 查看用户配置 $ cat ~/.gitconfig3 y8 P+ `/ E+ T. P& B8 O. a5 d # 查看当前项目的 git 配置1 e) I2 |, C" b9 b6 o $ cat .git/config/ O+ ]! p7 y; B m& o9 S; A3 F # 查看暂存区的文件 $ git ls-files # 查看本地 git 命令历史. Y$ y6 P, P6 X, L& y$ q* r $ git reflog # 查看所有 git 命令 $ git --help -a, k. O- j g$ q% t# U4 W # 查看当前 HEAD 指向5 R1 G# c% [3 v( R: y9 y* o6 O $ cat .git/HEAD # git 中 D 向下翻一行 F 向下翻页 B 向上翻页 Q 退出2 H: R/ U1 G. p. @+ m/ P5 v # 查看提交历史0 X1 w; d1 _ s9 x. t! s! _- J% t% z $ git log --oneline --grep="关键字"& J' t' |7 R/ B0 H) Y& q: _ --graph --all --author "username"' Y; [! v4 f5 w: y/ X' P5 Q+ M --reverse -num -p --before= 1 day/1 week/1 "2019-06-06"4 `- d9 y4 Y( S7 m) @6 I1 j6 y --after= "2019-06-06"* k3 ~9 l- K6 k- T" x* h7 y8 v2 C& W --stat# X M% d8 Y$ K( R: u --abbrev-commit --pretty=format:"xxx"9 g/ O1 E: b |- j+ y1 I 0 L" w; p3 }- A$ _4 I$ Z; D # oneline -> 将日志记录一行一行的显示 # grep="关键字" -> 查找日志记录中(commit提交时的注释)与关键字有关的记录 u0 y: A$ m- m9 I! [0 K) a& d # graph -> 记录图形化显示 !!! # all -> 将所有记录都详细的显示出来 # author "username" -> 查找这个作者提交的记录 # reverse -> commit 提交记录顺序翻转 # before -> 查找规定的时间(如:1天/1周)之前的记录' f9 d/ U$ x6 i$ R$ E6 k- d- ]. ] # num -> git log -10 显示最近10次提交 !!! # stat -> 显示每次更新的文件修改统计信息,会列出具体文件列表 !!! # abbrev-commit -> 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符 !!! # pretty=format:"xxx" -> 可以定制要显示的记录格式 !!!5 i! I3 H# H0 t( j$ V* k # p -> 显示每次提交所引入的差异(按 补丁 的格式输出)!!! 8 s8 T1 {( f# ^* C0 U git reflog
符号解释: * 表示一个 commit| 表示分支前进+ L" J3 G+ p. a$ I+ M / 表示分叉 \ 表示合入 |/ 表示新分支 Git 常用命令 # 查看工作区和暂存区的状态 1 r9 x3 `! g, \4 ]+ v $ git status # 将工作区的文件提交到暂存区/ E' @& W: [+ U a' | $ git add . # 提交到本地仓库1 C: f; q1 |/ Q4 u7 |$ V $ git commit -m "本次提交说明" # add和commit的合并,便捷写法(未追踪的文件无法直接提交到暂存区/本地仓库) $ git commit -am "本次提交说明" # 将本地分支和远程分支进行关联 $ git push -u origin branchName # 将本地仓库的文件推送到远程分支 T. ?- U' z" I4 |" J $ git push. b& K6 m! s2 s: f2 O- B! S # 拉取远程分支的代码& {& V% _7 K* p, B: x, y( i2 d& C3 u $ git pull origin branchName # 合并分支; g1 F$ P: h. B5 o6 _# B: T $ git merge branchName # 查看本地拥有哪些分支 $ git branch # 查看所有分支(包括远程分支和本地分支) $ git branch -a4 B( O1 {* z4 Q7 X# p/ n # 切换分支 $ git checkout branchName # 临时将工作区文件的修改保存至堆栈中 I- d, W. Z( }' V; a( { $ git stash # 将之前保存至堆栈中的文件取出来$ i! f2 M4 v$ f! k1 { $ git stash pop* L; A/ d+ e! K6 e8 x; | / i7 U3 b) n0 d* g Git 常用命令详解add 将工作区的文件添加到暂存区 # 添加指定文件到暂存区(追踪新增的指定文件)$ git add [file1] [file2] ...% S a7 ]+ ?- s& B # 添加指定目录到暂存区,包括子目录 $ git add [dir]3 k3 u$ s7 c$ D # 添加当前目录的所有文件到暂存区(追踪所有新增的文件) $ git add . # 删除工作区/暂存区的文件 $ git rm [file1] [file2] ...+ C2 r) z! S7 f: e+ r- j I # 停止追踪指定文件,但该文件会保留在工作区9 O! f: O' p- ~- |- b- L $ git rm --cached [file], Q: m( J0 Q0 w' }! { # 改名工作区/暂存区的文件 $ git mv [file-original] [file-renamed] r! {/ I2 M# q" R$ z5 Z # Git 2.0 以下版本 #只作用于文件的新增和修改# r+ k5 C. s, a/ w* L $ git add . #只作用于文件的修改和删除0 |0 E# Z$ A/ P $ gti add -u' ^8 Q: ?. f6 R2 E) j& X #作用于文件的增删改' u N! p7 y" O' t# e7 j $ git add -A # Git 2.0 版本2 V8 y% m. j. K& U- B/ m $ git add . 等价于 $ git add -A
# 查看工作区和暂存区的状态 $ git status8 K- n1 {) @. J4 z commit # 将暂存区的文件提交到本地仓库并添加提交说明 $ git commit -m "本次提交的说明" # add 和 commit 的合并,便捷写法: C0 v/ e `: o! W+ R # 和 git add -u 命令一样,未跟踪的文件是无法提交上去的 $ git commit -am "本次提交的说明"- `) m' f; o3 \+ c- J3 M6 g # 跳过验证继续提交 $ git commit --no-verify, G3 g X9 I4 I+ n- H9 { $ git commit -n 3 j' ^1 Z) i. ?. D a3 ^/ | # 编辑器会弹出上一次提交的信息,可以在这里修改提交信息 $ git commit --amend+ n+ c P- Q1 m0 Q5 H3 k h # 修复提交,同时修改提交信息 $ git commit --amend -m "本次提交的说明" # 加入 --no-edit 标记会修复提交但不修改提交信息,编辑器不会弹出上一次提交的信息 $ git commit --amend --no-edit! {0 U; I5 z: c
# 如果远程仓库没有这个分支,会新建一个同名的远程分支 # 如果省略远程分支名,则表示两者同名 $ git push <远程主机名> <本地分支名>:<远程分支名> d& ~3 d) N) Y9 U7 p3 Q# r! u% V" A $ git push origin branchname, Q1 [+ C, Q# O 3 Z' ?: |5 a6 }* F% i # 如果省略本地分支名,则表示删除指定的远程分支 # 因为这等同于推送一个空的本地分支到远程分支。) m% U& C4 f6 J8 K0 E" V $ git push origin :master% N) k% k! _: H, _3 \/ V M # 等同于6 }. U1 }9 x: _ N) j. Q$ \ $ git push origin --delete master* H- M8 A' z" I # 建立当前分支和远程分支的追踪关系 $ git push -u origin master # 如果当前分支与远程分支之间存在追踪关系 # 则可以省略分支和 -u $ git push : W$ y# [. a5 p6 I # 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机3 M' P7 U" m( ?" X5 O $ git push --all origin0 V/ a: \" r) N5 b # 拉取所有远程分支到本地镜像仓库中 $ git pull # 拉取并合并项目其他人员的一个分支 $ git pull origin branchname # 等同于 fetch + merge& F8 a x+ L3 J8 \9 ?1 D $ git fetch origin branchName $ git merge origin/branchName3 A4 Y2 `" c# u! {8 M : l, X2 s5 u; L1 S # 如果远程主机的版本比本地版本更新,推送时 Git 会报错,要求先在本地做 git pull 合并差异,' ~* `# L9 U+ e7 [ # 然后再推送到远程主机。这时,如果你一定要推送,可以使用 –-force 选项1 H- I0 f/ s5 X$ `5 H9 W# g2 D8 k # (尽量避免使用) $ git push --force origin | git push -f origin branch # 查看本地分支 4 m" t( a9 m0 I& z $ git branch | git branch -l # 查看远程分支' N2 G& `# C. Q; A& T5 ~3 L; e $ git branch -r3 |" Z* [" N, |6 v% `+ s2 v. _; i9 Y # 查看所有分支(本地分支+远程分支) $ git branch -a # 查看所有分支并带上最新的提交信息1 K: S% J6 T5 V2 T! M$ e $ git branch -av" v C: E4 r+ L/ B7 a* } # 查看本地分支对应的远程分支# q, N# j0 K; h3 y8 j $ git branch -vv ! Q1 i7 A0 {( Y* j9 N # 新建分支/ w8 u( ]2 V5 j$ p( t( i # 在别的分支下新建一个分支,新分支会复制当前分支的内容 # 注意:如果当前分支有修改,但是没有提交到仓库,此时修改的内容是不会被复制到新分支的 $ git branch branchname4 u; K6 A3 y3 m- d( q0 u. {, L" i # 切换分支(切换分支时,本地工作区,仓库都会相应切换到对应分支的内容) $ git checkout branchname/ X+ L" O/ G/ G" b! |+ F1 |. K8 F # 创建一个 aaa 分支,并切换到该分支 (新建分支和切换分支的简写)! e; o1 G8 a. X- l4 _# a* V $ git checkout -b aaa5 m5 F; z l1 H) I F7 h3 {. A # 可以看做是基于 master 分支创建一个 aaa 分支,并切换到该分支 $ git checkout -b aaa master- h: _7 B# s5 Z1 _9 K4 \+ j8 o# @9 \; x # 新建一条空分支(详情请看问题列表)- _8 E& [/ U2 V" U: n $ git checkout --orphan emptyBranchName9 V5 z* {4 y! y& Z5 C- Y $ git rm -rf . 1 u# U" O9 m7 C) M M) G% p, R- F' } # 删除本地分支,会阻止删除包含未合并更改的分支2 G' C$ o! c8 k7 A! o1 c2 } $ git brnach -d branchname # 强制删除一个本地分支,即使包含未合并更改的分支 $ git branch -D branchname& m! M0 \( o4 q d P, D # 删除远程分支/ D( z, y, ]; p6 Q& ^: l # 推送一个空分支到远程分支,其实就相当于删除远程分支' u- E8 {6 C" y6 j8 b $ git push origin :远程分支名 # 或者 $ git push origin --delete 远程分支名* \* s. v! ?' G, x 0 P7 W0 B, S( v+ p+ }: n9 T7 ?. N) l # 修改当前分支名" m7 f: b$ P7 M: n6 }0 a4 a2 F $ git branch -m branchname merge 三种常用合并方法' w8 `& u" t) O- H; f8 q7 u # 默认 fast-forward ,HEAD 指针直接指向被合并的分支% m! X5 W" g; V+ L0 g $ git merge% z) K( ?1 k* s8 d3 D: e# x & i; f+ H/ ^4 n% a7 W # 禁止快进式合并3 e) K, F; ~; ~( i* w6 y $ git merge --no-ff* u- M: J3 N/ j0 d- l9 S 3 F& h, j6 M& e0 }# h% r) `6 a' X $ git merge --squash/ M3 m, O$ [& s7 Q( r. M ![]()
www.liaoxuefeng.com/wiki/896043… git-scm.com/book/zh/v2/… www.jianshu.com/p/4a8f4af4e… juejin.im/post/5a5438… stash
「使用场景:」 当你接到一个修复紧急 bug 的任务时候,一般都是先创建一个新的 bug 分支来修复它,然后合并,最后删除。但是,如果当前你正在开发功能中,短时间还无法完成,无法直接提交到仓库,这时候可以先把当前工作区的内容 git stash 一下,然后去修复 bug,修复后,再 git stash pop,恢复之前的工作内容。 # 将所有未提交的修改(提交到暂存区)保存至堆栈中$ git stash' p7 t0 ^2 x3 {9 i' ^5 `! G' c3 } # 给本次存储加个备注,以防时间久了忘了. ]6 T4 S# U7 v- m $ git stash save "存储"" i9 [" `8 p9 h& a3 R # 存储未追踪的文件$ \ E+ w& ?( [/ W4 `: M $ git stash -u+ N3 ?/ G" h5 f# c9 N' D2 i1 R # 查看存储记录$ K% e5 D# M4 m, H $ git stash list 在 Windows 上和 PowerShell 中,需要加双引号 # 恢复后,stash 记录并不删除 $ git stash apply "stash@{index}"1 ^5 d2 l2 k/ E K9 _ # 恢复的同时把 stash 记录也删了 $ git stash pop "stash@{index}" # 删除 stash 记录2 N/ [5 \& J& |$ h $ git stash drop "stash@{index}" # 删除所有存储的进度+ h5 H' X6 r' H- s0 t8 u* j $ git stash clear # 查看当前记录中修改了哪些文件 $ git stash show "stash@{index}"1 m& ?+ H9 X% x! G3 t. P # 查看当前记录中修改了哪些文件的内容 $ git stash show -p "stash@{index}" ( x; i) w4 t' N diff # 查看工作区和暂存区单个文件的对比; l; L& @0 ^! j$ k $ git diff filename # 查看工作区和暂存区所有文件的对比9 z" x0 Y6 ?# g9 K# i/ ?( ? $ git diff # 查看工作区和暂存区所有文件的对比,并显示出所有有差异的文件列表 $ git diff --stat/ R# }" c& h, [2 Y6 P b # 注意: # 1.你修改了某个文件,但是没有提交到暂存区,这时候会有对比的内容 # 一旦提交到暂存区,就不会有对比的内容(因为暂存区已经更新) # 2.如果你新建了一个文件,但是没有提交到暂存区,这时候 diff 是没有结果的 3 Z: g& X8 W' i; C3 X 1 l9 Z. E; ~/ i) _ # 查看暂存区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比5 u; a3 p) w8 s6 {6 a; o. p $ git diff --cached/--staged2 j6 f3 d! B0 a # 查看工作区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比9 a7 |. J+ F8 |5 A% }) {; W2 [) L $ git diff branchname # 查看工作区与 HEAD 指向(默认当前分支最新的提交)的对比 $ git diff HEAD9 V; [, i! a- `2 A # 查看两个本地分支中某一个文件的对比8 X, F2 T* J6 `6 m6 s6 a! ` $ git diff branchname..branchname filename/ w6 Y' K7 G& f0 `( i ~% R; [4 i5 e) B # 查看两个本地分支所有的对比 $ git diff branchname..branchname( K) f: C, E) L0 ?7 L8 h # 查看远程分支和本地分支的对比 $ git diff origin/branchname..branchname # 查看远程分支和远程分支的对比 $ git diff origin/branchname..origin/branchname! X8 L+ o% U i$ k 7 f2 d- f. g3 g/ n" b: o+ n: P # 查看两个 commit 的对比' i, C% F D4 i6 Q" F8 w8 Y $ git diff commit1..commit2 % k6 H' I( Z1 C' Q# A) V/ B& _ remote # 查看所有远程主机5 P3 Z0 ^9 r3 V! }2 O4 i% x4 [ 9 A' Z2 [! U3 H) X+ V3 L $ git remote, x5 K1 G% y1 j& q # 查看关联的远程仓库的详细信息 $ git remote -v5 L4 a0 i1 l. L, ? # 删除远程仓库的 “关联” $ git remote rm projectname- m' U3 R( ^+ p. H' \; ^+ w6 _. |& R # 设置远程仓库的 “关联”5 b8 b) S$ I8 M% v5 P $ git remote set-url origin <newurl> tag 常用于发布版本 www.liaoxuefeng.com/wiki/896043… # 默认在 HEAD 上创建一个标签$ git tag v1.0 # 指定一个 commit id 创建一个标签% X* L3 @+ W' o3 x' g* {; q $ git tag v0.9 f52c633/ t, m5 k- ~8 y # 创建带有说明的标签,用 -a 指定标签名,-m 指定说明文字 $ git tag -a v0.1 -m "version 0.1 released", M0 j W; y( c9 j; [ * J4 M7 T# s5 c9 w- Z # 查看所有标签1 i4 S, A0 S6 D% D- ` ] # 注意:标签不是按时间顺序列出,而是按字母排序的。 $ git tag: D8 n) x; r0 S5 C$ h ) n/ B; V3 ?( x- T @4 \4 }- g # 查看单个标签具体信息8 w6 y7 ~. L( q" R+ h0 W9 P) X. Z $ git show <tagname> # 推送一个本地标签- i5 q( H- R( [+ M9 l. O( b $ git push origin <tagname> # 推送全部未推送过的本地标签 $ git push origin --tags # 删除本地标签 # 因为创建的标签都只存储在本地,不会自动推送到远程。 # 所以,打错的标签可以在本地安全删除。 $ git tag -d v0.1 # 删除一个远程标签(先删除本地 tag ,然后再删除远程 tag) $ git push origin :refs/tags/<tagname>% Y& D2 n* t0 O U! r1 A) n 删除文件 # 删除暂存区和工作区的文件 4 ~$ l1 p7 Z2 u3 }8 j$ r1 s $ git rm filename( b9 X& k- l$ }# w: s # 只删除暂存区的文件,不会删除工作区的文件 $ git rm --cached filename, Y4 U% ]8 V- S" R- ]# J 如果在配置 .gitignore 文件之前就把某个文件上传到远程仓库了,这时候想把远程仓库中的该文件删除,此时你配置 .gitignore 文件也没有用,因为该文件已经被追踪了,但又不想在本地删除该文件后再重新提交到远程仓库,这时候可以使用 git rm --cached filename 命令取消该文件的追踪,这样下次提交的时候,git 就不会再提交这个文件,从而远程仓库的该文件也会被删除 版本切换 & 重设 & 撤销
$ git checkout <filename> # 恢复暂存区的所有文件到工作区 $ git checkout ." M, y: w& C; C* |! r* v7 Z, A: _ # 回滚到最近的一次提交' b# `- c3 {- c6 K( ^ # 如果修改某些文件后,没有提交到暂存区,此时的回滚是回滚到上一次提交4 N# d6 C+ ]# D3 _ # 如果是已经将修改的文件提交到仓库了,这时再用这个命令回滚无效 # 因为回滚到的是之前自己修改后提交的版本7 I/ [6 b8 W& Z" Z $ git checkout HEAD0 S4 ?& O$ Z# J, e9 T $ git checkout HEAD -- filename # 回滚到最近一次提交的上一个版本 $ git checkout HEAD^/ V4 ?5 e' d& j/ t* Z3 ? # 回滚到最近一次提交的上2个版本" D& Z& i9 W4 I9 P $ git checkout HEAD^^ # 切换分支,在这里也可以看做是回到项目「当前」状态的方式 $ git checkout <当前你正在使用的分支> # 切换到某个指定的 commit 版本4 b7 X& ?* z7 `0 n $ git checkout <commit_id>2 A) u) h# A9 Q, T( T/ k* X # 切换指定 tag $ git checkout <tag>4 Z- U7 C( n. [. o$ f; U5 I; O 2 a- v( F4 U `( C" D9 |
![]() ![]() ![]() git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD]:将当前的分支重设(reset)到指定的 <commit> 或者 HEAD (默认,如果不显示指定<commit>,默认是 HEAD ,即最新的一次提交),并且根据 [mode] 有可能更新索引和工作目录。mode 的取值可以是 hard、soft、mixed、merged、keep 。 # 从暂存区撤销特定文件,但不改变工作区。它会取消这个文件的暂存,而不覆盖任何更改( t3 I4 t* w$ w: _. P" G- p. f$ git reset <fileName> # 重置暂存区最近的一次提交,但工作区的文件不变 $ git reset8 z5 ~# C- F9 N# e: `# @! Y # 等价于 $ git reset HEAD (默认) # 重置暂存区与工作区,回退到最近一次提交的版本内容( Y! Q0 P/ f. I& r $ git reset --hard6 i9 b: G. s* B) b # 重置暂存区与工作区,回退到最近一次提交的上一个版本 $ git reset --hard HEAD^+ e B9 r$ n0 e 8 C# w- L9 x+ F9 q0 q) ^ # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区,但工作区不变; _! ?4 W' Y; \8 b4 a! |( v $ git reset <commit>2 ?/ v. x/ P1 x, _ e" K: ?) G8 y7 y # 等价于 $ git reset --mixed <commit>9 ]$ Y2 N+ g0 ~6 j- e. { : I1 ~' o% F* F$ B/ ~8 ?9 ] # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),但保持暂存区和工作区不变 $ git reset --soft <commit>! F. s7 X# ]+ n3 d# w # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区、工作区 $ git reset --hard <commit>
「我们可以用 git reflog 查看历史命令,这样就可以看到之前新版本的 commit_id ,然后 git reset --hard commit_id 就可以回到之前的新版本代码」
# 生成一个撤销最近的一次提交的新提交 L( _, d$ k* H $ git revert HEAD # 生成一个撤销最近一次提交的上一次提交的新提交+ L% ^' J6 ]/ C2 u: V4 v $ git revert HEAD^/ q P- k2 u& U) K9 U # 生成一个撤销最近一次提交的上两次提交的新提交1 z$ J2 h; W& ^ J! Q $ git revert HEAD^^5 G W9 l, L, }" E* W' y- { # 生成一个撤销最近一次提交的上n次提交的新提交 $ git revert HEAD~num' Z }8 _- B# R9 E/ E # 生成一个撤销指定提交版本的新提交 $ git revert <commit_id>6 A8 U2 J7 u$ p/ _7 ` # 生成一个撤销指定提交版本的新提交,执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息" D0 H: z% n" `2 d5 r6 y4 }) N6 _% u $ git revert <commit_id> --no-edit: h: T& g; t v$ i2 A+ a git revert命令用来「撤销某个已经提交的快照(和 reset 重置到某个指定版本不一样)」。它是在提交记录最后面加上一个撤销了更改的新提交,而不是从项目历史中移除这个提交,这避免了 Git 丢失项目历史。 「撤销(revert)应该用在你想要在项目历史中移除某个提交的时候」。比如说,你在追踪一个 bug,然后你发现它是由一个提交造成的,这时候撤销就很有用。 「撤销(revert)被设计为撤销公共提交的安全方式,重设(reset)被设计为重设本地更改。」 因为两个命令的目的不同,它们的实现也不一样:重设完全地移除了一堆更改,而撤销保留了原来的更改,用一个新的提交来实现撤销。「千万不要用 git reset 回退已经被推送到公共仓库上的 提交,它只适用于回退本地修改(从未提交到公共仓库中)。如果你需要修复一个公共提交,最好使用 git revert」。 发布一个提交之后,你必须假设其他开发者会依赖于它。移除一个其他团队成员在上面继续开发的提交在协作时会引发严重的问题。当他们试着和你的仓库同步时,他们会发现项目历史的一部分突然消失了。一旦你在重设之后又增加了新的提交,Git 会认为你的本地历史已经和 origin/master 分叉了,同步你的仓库时的合并提交(merge commit)会使你的同事困惑。 cherry-pick「将指定的提交 commit 应用于当前分支」(可以用于恢复不小心撤销(revert/reset)的提交) $ git cherry-pick <commit_id>1 S9 Z3 _/ k' } n$ git cherry-pick <commit_id> <commit_id>1 e, h: t* M- _/ y2 j* y$ } $ git cherry-pick <commit_id>^..<commit_id> git submodule 子模块 有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。也许是第三方库,或者你独立开发的,用于多个父项目的库。现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。如果将另外一个项目中的代码复制到自己的项目中,那么你做的任何自定义修改都会使合并上游的改动变得困难。「Git 通过子模块来解决这个问题,允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。」 # 在主项目中添加子项目,URL 为子模块的路径,path 为该子模块存储的目录路径; p5 p+ B/ T* A9 @git submodule add [Path] # 克隆含有子项目的主项目9 ?1 K1 k0 W0 [4 W4 z9 E: o5 N7 C$ k git clone [URL] # 当你在克隆这样的项目时,默认会包含该子项目的目录,但该目录中还没有任何文件5 S0 @; L8 }( g. i" X* r8 T # 初始化本地配置文件4 r1 b) i) M- \& x5 m git submodule init # 从当前项目中抓取所有数据并检出父项目中列出的合适的提交( y$ G4 h5 \! L0 z git submodule update # 等价于 git submodule init && git submodule update3 B* d7 {; _" H f' W5 d' V git submodule update --init " ^) [3 l0 ^1 O # 自动初始化并更新仓库中的每一个子模块, 包括可能存在的嵌套子模块7 H( p5 r/ l$ S2 a git clone --recurse-submodules [URL] A# y( `3 p4 d# ^" ]) | 新建一个 Git 项目的两种方式1.本地新建好 Git 项目,然后关联远程仓库 # 初始化一个Git仓库7 s a8 k; F6 \3 @ $ j- e( z( m: s/ c' M' K $ git init* D% F. U( V9 K1 B # 关联远程仓库 $ git remote add <name> <git-repo-url> # 例如1 Z$ @9 Y8 _. h* F' U. h $ git remote add origin [url=http://github.com/xxxxxx]http://github.com/xxxxxx: d4 C; U. X' f 2.clone 远程仓库! i1 T2 F- Z- t& u' U& V # 新建好远程仓库,然后 clone 到本地7 ~' U! T+ G, b9 R8 @ 2 c4 ?+ E) n8 q! Y $ git clone <git-repo-url>0 _1 D. Z. ]6 I% k. n0 f # 将远程仓库下载到(当前 git bash 启动位置下面的)指定文件中,如果没有会自动生成) W/ a9 F7 U @1 v+ i3 p5 P3 Q $ git clone <git-repo-url> <project-name> Git 分支管理规范 blog.csdn.net/LitongZero/… juejin.im/post/5b4328…
「预发布环境的作用:」 预发布环境是正式发布前最后一次测试。因为在少数情况下即使预发布通过了,都不能保证正式生产环境可以100%不出问题;预发布环境的配置,数据库等都是跟线上一样;有些公司的预发布环境数据库是连接线上环境,有些公司预发布环境是单独的数据库;如果不设预发布环境,如果开发合并代码有问题,会直接将问题发布到线上,增加维护的成本。 Git 钩子
4.3 配置脚本 「如果没有在 .git->hooks 目录下生成 pre-commit 文件的话,则要手工创建node ./node_modules/pre-commit/install.js」 "scripts": {"build": "tsc",7 i5 Y9 M: p% L. ~* ]' Y1 y; j "eslint": "eslint src --ext .ts", "eslint:fix": "eslint src --ext .ts --fix" },$ n- F! e% k$ R% c! _5 a, K; H" H //在提交代码之前,先执行 scripts 中的 eslint 命令 "pre-commit": [ "eslint" ]: T" Q# G: I3 q' c 2 h6 Q2 c9 l& O4 \3 j+ y 4.4 跳过 pre-commit 继续提交代码3 }* \ @+ Y0 v4 S. w; r' X # 跳过验证6 w5 t* q% w/ d6 j1 L5 @. X; n $ git commit --no-verify8 ^- v: z# R/ f# {6 l Z $ git commit -n 更多钩子:git-scm.com/book/zh/v2/… 常见问题1、拉取别人的远程分支合并后,git 会存取这个拉取的记录,如果你不小心删了别人的上传的文件,这时候想要再拉取别人的分支是没用的,会显示 already-up这时候可以回滚代码,重新拉取。 2、以前有过这样的经历:前后端、客户端的代码都存放在一个 git 仓库中,在根目录下各自新建项目目录。那么可以直接在自己的项目目录下使用 git 提交代码并且在各自的项目目录下配置 .gitignore 文件,不用在根目录下配置 .gitignore 文件,这样就互不影响了3、fatal:refusing to merge unrelated histories 拒绝合并不相关的历史在 git 2.9.2 之后,不可以合并没有相同结点的分支(分支之间自仓库建立后,从来没有过互相拉取合并)。如果需要合并两个不同结点的分支,如下: $ git pull origin branchName --allow-unrelated-histories" }1 y8 V5 J& L5 {/ F2 F% c" |$ git merge branchName --allow-unrelated-histories 这个功能是可以让大家不要把仓库上传错了,如果会加上这个代码,那么就是自己确定了上传。旧版本的 Git 很容易就把代码传错了,现在可以看到,如果上传的不是之前的,那么就需要加代码上传。正常情况下,都是先建立仓库,然后切多个分支,分支先去拉取合并主分支的内容,然后再各自开发, 如果建立仓库后,各个分支没有区拉取主分支的代码,之后各个分支之间想要合并时就会报错。 4、合并分支时出现问题,想要解除合并状态error: merge is not possible because you have unmerged files.1 k; P4 @ J& h- \+ n8 e 8 w% [2 j6 e# V2 d8 \% a! Q% l hint: Fix them up in the work tree, and then use 'git add/rm <file>' |7 N' y" d! E' U- \2 ? hint: as appropriate to mark resolution and make a commit. fatal: Exiting because of an unresolved conflict.. y4 Z$ j- I: c; B" \/ `9 T9 ^/ V- v 当远程分支和本地分支发生冲突后,git 保持合并状态,你如果没有去解决完所有的冲突,那么 git 会一直保持这个状态,你就无法再提交代码。只有先解除合并状态后,才能继续提交。执行命令前最好先备份一下,有可能本地做的修改会被远程分支覆盖掉。 # 解除合并状态$ git merge --abort, v5 |6 k9 J# [* G j7 c$ g& | 5、不小心把某些文件上传到远程 git 仓库/想要删除远程仓库中的文件 # 删除暂存区和工作区的文件1 V' m7 N0 q2 D4 A$ { $ git rm filename # 只删除暂存区的文件,不会删除工作区的文件 $ git rm --cached filename7 D$ }% Q) p y+ Z) O' m 如果在配置 .gitignore 文件之前就把某个文件上传到远程仓库了,这时候想把远程仓库中的该文件删除,此时你配置 .gitignore 文件也没有用,因为该文件已经被追踪了,但又不想在本地删除该文件后再重新提交到远程仓库,这时候可以使用 git rm --cached filename 命令取消该文件的追踪,这样下次提交的时候,git 就不会再提交这个文件,从而远程仓库的该文件也会被删除 6、将本地新建的项目上传到新建的远程仓库上之前没有进行过关联,即没有通过 clone 远程项目到本地再开始做项目,而是先本地新建了一个项目,然后想传到远程仓库上。 # 将本地仓库和远程仓库关联起来/ a- J* Q) B8 Y% t; [* r1 m$ git remote add origin 远程仓库地址( z: [# `/ C4 m3 N$ L8 H+ ]8 d1 | # 将本地的 master 分支推送到 origin 主机,同时指定 origin 为默认主机4 N8 t- r- @ d7 q $ git push -u origin master$ }5 U* m3 Q7 i8 x* {1 F. K # 上面的命名执行后,下次再从本地库上传内容的时候只需下面这样就可以了* E+ ~+ y, `. A2 W) W $ git push; I( \3 x; T @, O# E9 E7 X- u 7、HEAD 指针既可以指向分支(默认指向当前分支),也可以指向快照,当指向的是快照时,这个时候指针的状态称之为游离状态(detached)8、创建与合并分支的原理 www.liaoxuefeng.com/wiki/896043… 9、每次 git push 都要输入用户名、密码
# Generating public/private rsa key pair... # 三次回车即可生成 ssh key% f8 n+ {- w. A9 \ V) K# ], r
![]() 测试 ssh 是否能够连接成功 $ ssh -T git@github.com5 C9 ^3 O( m+ f3 I% v
![]() 「使用 ssh 协议」 $ git remote set-url origin git@xxx.com:xxx/xxx.git
一般为 C:\users\Administrator,也可以是你自己创建的系统用户名目录,文件名为 .git-credentials。由于在 Windows 中不允许直接创建以 "." 开头的文件,所以用命令行创建该文件。 $ touch .git-credentials1 ~( P: K/ ]# G% M$ echo "http://{username}:{password}@github.com" >> ~/.git-credentials5 _) C% \" K! m' i1 Q X5 C y6 \ $ git config --global credential.helper store* V9 Z! l' G$ f7 t4 ]3 y1 i: ^- J 10、git 不允许提交空文件夹 可以在当前目录下,添加一个 .gitkeep 文件 11、有时候复制过来的文件,使用 git add . 无法进行文件追踪,可以使用 git add -A ,这也就是每次提交前都要 git status 的原因12、同一台电脑配置多个 git 账号github.com/jawil/notes… 13、Another git process seems to be running in this repository, e.g.![]() 原因在于 Git 在使用过程中遭遇了奔溃,部分被上锁资源没有被释放导致的。 「解决方案:」 进入项目文件夹下的 .git 文件中(显示隐藏文件夹或 rm .git/index.lock)删除 index.lock 文件即可。 14、git commit -am "xxx" 有时候会失效,无法提交所有的修改git commit -am "xxx" 只会将被 「tracked」 的文件添加到暂存区并提交,而将文件添加到 git 管理是要使用 git add 命令,将新的文件 「tracked」 。(新建了文件之后,idea 会提示你是否需要加到 git 管理中。选择记住后,之后 idea 默认都会把新建的文件 「tracked」 化) 15、git merge --no-ff 的作用
![]() 从合并后的代码来看,结果都是一样的,区别就在于 --no-ff 会让 git 生成一个新的提交对象。为什么要这样?通常我们把 master 作为主分支,上面存放的都是比较稳定的代码,提交频率也很低,而 feature 是用来开发特性的,上面会存在许多零碎的提交,快进式合并会把 feature 的提交历史混入到 master 中,搅乱 master 的提交历史。所以如果你根本不在意提交历史,也不爱管 master 干不干净,那么 --no-ff 其实没什么用。 segmentfault.com/q/101000000… 16、git merge 与 git rebase 的区别juejin.im/post/5a5438… blog.csdn.net/liuxiaoheng… segmentfault.com/a/119000001… segmentfault.com/a/119000001… 17、git log 无法正常显示中文# 试试 Y' y y( K# s8 U3 i7 ~ + X! ^0 q6 r _4 F $ git -c core.pager=more log # 如果可以显示中文的话,把 pager 设置为 more $ git config --global core.pager more. V$ `+ Y% n0 F0 Q7 t' y www.zhihu.com/question/57… www.playpi.org/2019031901.… 18、git merge -m "xxx" 的时候可以附加信息
![]() 19、git pull 会拉取所有远程分支的代码到本地镜像仓库中9 u: O# B, r' U! X) p 想要 merge 别人的分支时:
![]() 20、git branch -r/-a/-l 查看的都是本地镜像仓库中的分支,如果本地镜像仓库没有拉取远程仓库的代码,此时别人新推了一个分支到远程仓库,你这时候是查看不到这条新推的分支的21、git stash 存储未追踪的文件9 q+ n; a p3 [4 @, B
22、如何在 github 上 pr 项目 segmentfault.com/a/119000002… 23、git push 无法提交代码「可能出现的报错:」
$ cat .git/config0 ?' _6 v+ h0 d5 P/ t( i$ \/ M' Q
![]() 24、git 输错用户名和密码,后续的 git 操作一直报错 remote: Coding 提示: Authentication failed. remote: 认证失败,请确认您输入了正确的账号密码。 fatal: Authentication failed for 'http://e.coding.net/xxx.git/' 在控制面板里找到凭据管理器,选中 Windows 凭据,找到 git 的凭据,点击编辑,输入所用 github 的正确用户名和密码。 ![]() 25、lint-staged 失败 ![]() 可能你的项目名路径中包含了中文名,需要替换成英文名 26、查看 git 安装目录
31、如果两个人都对某个文件进行了修改,一个是重命名文件,一个是修改文件内容,那么会起冲突吗?git 很智能,会自动合并这些修改 如果两个人都对同一个文件重命名,此时会起冲突,git 不会自动处理,需要开发者自身去解决冲突 32、git revert 失败:error: Commit faulty merge is a merge but no -m option was given、error: option `mainline' expects a number greater than zerosegmentfault.com/a/119000001… www.jianshu.com/p/3719dae37… git revert -m 133、git 创建一个空的分支 在 Git 中创建分支,是必须有一个父节点的,也就是说必须在已有的分支上来创建新的分支,如果工程已经进行了一段时间,这个时候是无法创建空分支的。但是有时候就是需要创建一个空白的分支。 $ git checkout --orphan emptyBranchName9 X. {( `' u- b& Q# q4 S5 \该命令会生成一个叫 emptybranch 的分支,该分支会包含父分支的所有文件。但新的分支不会指向任何以前的提交,就是它没有历史,如果你提交当前内容,那么这次提交就是这个分支的首次提交。 想要空分支,所以需要把当前内容全部删除,用 git 命令 $ git rm -rf . // 注意:最后的‘.’不能少。34、如何清空一个分支的所有提交 先删除该分支,然后再新建一个空的分支(分支名就是删除的分支名)~~ " p6 ?. f) `! [) l |
希望楼主多多分享,赠人玫瑰,手有余香,念念不忘,必有回响;