GITusage

分区

工作区:仓库目录
版本库:.git隐藏目录
暂存区:存放在版本库中,叫stage或index

git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支,然后Stage就空了。

可以想象成,工作区的文件、stage中的文件和分支中的文件是3个独立的文件。

[工作区] --(add)-> [版本库: stage --(commit)-> master分支]

日常操作

git init # Git管理仓库初始化
git add xxx.xx #添加文件
git add --all # git add -A
git commit -m "xx" # 添加 commit
git status # 查看状态
git diff xxx.xx # 查看文件变化
git diff HEAD -- xxx.xx # 查看工作区和版本库里面最新版本的区别

回到过去

git log 显示提交日志 会输出每个版本的 commit id。

HEAD指针指向当前版本,有多少个^就表示前多少个版本,或者用~N指定前N个版本,HEAD^^^HEAD~3等价。

git reset --hard HEAD^
git reset --hard 111ax

退回到旧版本,无法再查看新版本的 commit id,因此需要git reflog查看最近的操作(reflog: 引用日志,可以查看所有分支的所有引起HEAD指针变动的操作),记下Commit ID,--hard后面可接Commit ID的前几位,git会自动匹配。

丢弃修改

在commit之前,使用git status会提示如何撤销修改,使用git restore <file>或者git resotre --staged <file>。对于只在工作区的情况,用前者直接丢弃工作区。对于进入暂存区stage的情况,用后者只是将文件移出暂存区,还需要再次restore才能复原。

删记录

git checkout --orphan latest_branch # 切换新分支
git add -A # 缓存所有文件(除.gitignore中的)
git commit -am "xxx" # 提交跟踪过的文件
git branch -D master # 删除master分支
git branch -m master # 重命名当前分支为master
git push -f origin master # 提交到远程master分支

Github远程仓库

首次执行:

git config --global user.name "Nickname"
git config --global user.email "Email@em.com"
# git config --global core.quotepath false (显示中文问题)

生成并查看SSH:

ssh-keygen -t rsa -C "Email@em.com"
cat ~/.ssh/id_rsa.pub
# ls ~/.ssh/  -- id_rsa是私钥,id_rsa.pub是公钥

将公钥添加到Github/Gitee即可使用

添加远程仓库:

git remote add Repository_Name Git_Address
git push -u Repository_Name master # 第一次推送到远程的空仓库 以后不需要-u指令
git remote -v # 查看远程仓库
git remote rm Repository_Name # 删除

分支

主分支即master分支,HEAD指向master分支指向提交,可以有其他分支,其他分支也指向提交HEAD可以指向这些分支。

         master
           ↓
⬜ → ⬜ → ⬜ → ⬜ 
                ↑
               Dev ← HEAD
git checkout -b dev # 从*当前分支*中创建分支dev,-b 参数表示创建并切换 或者git switch -c <name>
git branch # 查看当前分支
# ... 一些操作 完成开发
git checkout master # 切换回到master 或者git switch <name>
git merge dev # 把dev分支的工作成果合并到当前分支(master)
git log --graph --oneline # 简要显示log分支图
git branch -d dev # 删除dev分支

分支管理

合并分支时,如果可能,Git会用Fast forward模式,这样删除分支后,会丢掉分支信息。禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。用merge合并dev分支时,附上--no-ff,和-m "xxx"即可。

git merge --no-ff -m "merge with no-ff" dev

master仅用来发布新版本,每个人都有自己的分支,并且时不时地往dev分支上合并。

如果工作区有文件,或者已经添加到stage,但是没有在分区内部,那么切换到不同分支之后,工作区或者stage中的这个文件并不会被移动或者变化,只有已经添加到分区内部的文件会变化

masterdev分支需要远程同步;bug分支只用于在本地修复bug,没必要推到远程。feature分支是否推到远程,取决于是否多人在开发。

BUG分支

正在dev上的工作未完成,需要临时修bug。先储存现场,再在master上修复bug。由于master和dev上都存在bug,此时可用git cherry-pick复制一个特定的提交到当前分支。

以下测试中,master中有文件a和b,dev基于master再添加了文件c(未commit)

git add -A # 储存前需要放入stage
git stash # 储存现场
# 下面修复master分支的bug
git checkout master # 去master,准备在master中创建分支
git checkout -b bug-01
# do something, add, commit 输出commit id: 0f39c70
git checkout master # 回去master 准备把bug分支合并到master
git merge --no-ff -m "merged bug fix 01" bug-01
git log --graph --oneline
# 输出
# *   41ccef2 (HEAD -> master) merged bug fix 01
# |\
# | * 0f39c70 (bug-01) fix bug in a
# |/
# * cff1bad (dev) add b
# * 52621ca add a

# master修复完毕,复制修改到dev分支
git checkout dev
git cherry-pick 0f39c70 # 0f39c70是修复bug之后的commit id
git log --graph --oneline
# 输出
# * dfc9722 (HEAD -> dev) fix bug in a
# * cff1bad add b
# * 52621ca add a

# 修复bug完成,下面回dev干活
git checkout dev
git stash list # 查看储存的现场 输出:stash@{0}: WIP on dev: f52c633 add merge
git stash apply # 恢复 但stash内容不删除
git stash pop # 恢复 同时把stash内容删了
# 也可以 git stash apply stash@{0} 指定不同的stash

git checkout master
git merge dev
git log --graph --oneline
# 输出
# *   afc0842 (HEAD -> master) Merge branch 'dev'
# |\
# | * daa4e1f (dev) add c
# | * dfc9722 fix bug in a
# * |   41ccef2 merged bug fix 01
# |\ \
# | |/
# |/|
# | * 0f39c70 fix bug in a
# |/
# * cff1bad add b
# * 52621ca add a
git rebase dev
git log --graph --oneline
# * daa4e1f (HEAD -> master, dev) add c
# * dfc9722 fix bug in a
# * cff1bad add b
# * 52621ca add a

多人协作

多人协作修改了同一个文件,需要先pull下来,在本地处理完毕再push。Git会在有冲突的文件处作出标记,这时候就需要手动修改,然后再尝试下一步操作(push)。

# PC A
git checkout -b dev origin/dev # **创建远程的dev分支**,是在本地创建和远程分支对应的分支
# git add commit and push ... 

# PC B
git pull # 直接pull可能会失败,自然会有提示
git branch --set-upstream-to=origin/dev dev # 指定本地dev分支与远程origin/dev分支的链接
git pull # 再次尝试,然后修改文件冲突,再次push

执行git push --set-upstream origin dev,也就是说把本地分支与远端的dev分支关联在了一起,关联后,不用每次都git push origin dev , git pull origin dev而已。

其他

Push失败解决方案

  1. 备份本地文件,再pull下来手动融合文件,然后看一下status,git add -A一遍过,在commit -m,最后再push一遍。
  2. 强行push (使用-f)