Git速查手册

stash

  • git stash: 暂存没有add的修改
  • git stash list: 查看已经暂存的
  • git stash apply: 应用暂存的修改到当前分支

工作流

checkout & merge

1) git clone 检出代码:

  • 显示remote:(origin是远程库的名字)
  • git remote -v 查看可以抓取和推送的origin的地址
  • git remote show origin, 比上面的更详细, 可以看到git pull/push到的默认是哪个分支.

2) git checkout -b issue3 origin/master, 从远端的master分支创建一个自己的分支issue3

  • 创建新分支并立即切换到新分支: git checkout -b [name]
    • 如果这时候git pull从服务器拉新代码, 会失败并提示服务端的分支没有和新分支对应: git branch --set-upstream-to=origin/master [分支名]

3) 合并源分支(issue3) 到远程目标分支(master):

  • git pull --rebase origin master // 在issue3分支pull最新的master代码
  • git checkout master // 切换到目标分支
  • git merge --no-ff issue3 // --no-ff 禁用 Fast forward模式, 这样删除分支后也不会丢掉分支信息
  • git push origin master
  • 如果merge时出现冲突:
    • 修改冲突文件, 然后重新git add confilct_file(重新staged), 将把它们标记为已解决状态(译注:实际上就是来一次快照保存到暂存区域)。因为一旦暂存,就表示冲突已经解决。
    • 然后不要忘了: git commit -m "conflict fixed"
    • 解决完冲突, push上去git push origin master

4) 合并完成后, 删除开发分支:

  • git branch -d <branch_name> # 如果这个分支没有被merge,git会提示
  • git branch -D <branch_name> # -D就是强行删除
  • git push origin --delete <branch_name>如需要删除远程分支:

rebase

➤ 用rebase 合并commit记录:

  • 使用git rebase有两种:
    • git rebase -i HEAD~4 // 从HEAD开始往前4次commit合并成一个
    • git rebase -i star_commit end_commit // 前开后闭区间, 合并范围不包括start_commit, 如果不写end_commit则默认是HEAD
  • 进入vi模式(for example: 第一个commit标记为pick, 后面几个commit标记为squash, 这样会把后几个commit合并到第一个), wq保存退出, git会合并commit历史
    git-rebase.png

  • git log --graph --pretty=oneline --abbrev-commit 查看结果

  • 如果发生冲突, 修改后 git add ., 然后 git rebase --continue ..
  • rebase完, git log查看一下合并结果, 然后推到远端分支 git push -f origin <branch>

➤ merge之前使用git rebase:

  • 切换到私有分支, 然后 git rebase origin master // 与pull --rebase master的区别?
  • 如果有有冲突:
    • 修改冲突的文件, 然后 git add file
    • 修改完后, 不commit而是 git rebase --continue
    • 撤销此次Merge : git rebase --skip (可能多次)
  • git checkout master
  • git merge issue3

git rebase master发生了什么?

  • 把issue3分支每个commit取消掉, 并把这些commit保存到.git/rebase下作为临时patch)
  • 把当前分支(issue3)更新到最新的master
  • 把步骤1的patch应用到当前分支
  • ps: 解决冲突后继续git rebase --continue // 继续应用剩下的patch

cherry-pick

  • git cherry-pick <commit_hash> // 把这次commit应用到 当前分支, ps支持多个提交(空格分隔)
  • git cherry-pick <branch> // 把这个分支所有commit应用到 当前分支
  • 如果 cherry-pick 出现冲突, 修改完冲突需要再执行:
    • git add confilct_file
    • git commit -m "conflict fix"

撤销和回滚

  • 修改了文件, 但还没有git add: 输入git status, 会提示用git checkout -- file丢弃工作区, 文件回到服务器状态;
  • 修改并add了README.md, 还没有commit: 输入git status, 提示use git reset HEAD filename to unstage;
  • 如果已commit/已merge: git log -p -n 3 查看最近3次历史, 记录下commit的哈希值, 然后执行 git reset --hard commit_hashid
  • 如果已push:

    • git reflog 查看 commit_hashid
    • git reset --hard commit_hashid
    • git push -f // 把本地的修改强制推送到远程分支上
    • 强制推送到mster可能会报错,意思是没有权限之类的错误,报错如下。

      remote: GitLab: You don't have permission
      To git@10.255.223.213:code-ddreader/media-hapi.git
      ! [remote rejected] master (pre-receive hook declined)
    • 是因为master分支一般会成为保护分支,所以我们首先要去除master为保护分支,才可以强推。

有用的alias设置

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.hist "log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short"

以及: git config --global core.autocrlf false 使用LR而不是Win系统的CRLF

当你把git弄的一团糟时