计算机 · 2021年8月11日 0

git

版本控制软件

  • BitKeeper
  • CVS
  • SVN
  • Git
  • Mercurial

Git

BitKeeper不赞助Linux团队后,Linus就着手开发了Git。

Git学习资料

  • 官网: http://git-scm.com/
  • 可以通过man git查看git文档以获取关于git的详细介绍。使用git --html-path可以查看本地的git文档路径。

Git思想

Git缺点

  • 仓库比较大时(1GB)有性能问题
  • 存储二进制文件的每个版本,而不是采取计算变化量这种策略。

获取Git帮助

  • git help
  • git help command或者man git-command 获取关于某个命令 command 的帮助
  • git help -a/g 获取较全面的帮助

创建仓库(repository)

  • git init

配置Git

git config

用法:git config [<选项>]

  • 选择读配置还是写配置
    带有--get之类字样的显然就是读取配置。从Manual中可以看到还有增加、移除配置等选项。
  • 通过文件配置还是命令行选项配置
    可以在命令行中逐个配置键值对,或者git config [<file-option>] -e | --edit直接编辑配置文件,或者随便用个编辑器编辑相应的配置文件即可。
  • 配置的形式
  • 例子:
    git config [--global] user.name "Your name"
    git config [--global] user.emal you@email.com
    git config [--global] color.ui true
  • 配置范围
    通过file-option选项指定配置范围。
file-option含义
–system$(prefix)/etc/gitconfig中读写配置选项
–global~/.gitconfig中读写配置选项
–local(默认值).git/config中读写配置选项
–filefilename中读写配置选项

在进行git config操作时,如果是读操作,那么git依次从系统配置(system)、全局配置(global)和仓库配置(local)中读取配置,如果指定了file-option,那么git只从指定的位置读取配置。如果是写操作,那么git默认写到仓库配置里,如果指定了file-option,那么git就将配置写到file-option所代表的位置。

Git基本概念

  • 工作区(working directory)
  • 索引(INDEX)
  • commit
    A snapshot of your project.
  • HEAD
    当前分支(branch)的最后一次提交。

3.基本操作

  • 选择要要让git跟踪(track)的文件
    git add your-file
    git add .
    git add --all
    git add paths可以使用文件名的通配符表达式,如果路径被加上了双引号表示在整个项目文件中进行匹配,否则只在当前目录下进行匹配。
    git add *.txt当前目录;git add "*.txt"整个项目文件夹中匹配。
  • 查看修改
    git status查看自上一次提交(commit)以来,在工作目录所作的修改。
    git diff查看自上次提交以来,未暂存(unstaged)的修改
    git diff --staged查看已暂存的修改
  • 取消暂存
    git reset HEAD paths
    git reset HEAD
  • 放弃修改
    git checkout -- paths
  • 提交改变(commit)
    git commit
    git commit -m "This is a commit"
    git commit -a提交在已跟踪文件上作的全部改动
    git commit -am
  • 取消提交(undoing a commit)
    git reset --soft HEAD将上次提交的改动移到暂存区里(reset into staging)
    git reset --soft commit将HEAD移到commit,commit之后的提交都取消并将这些提交所做的改动都放到暂存区(staged)里去。
    git reset --hard commit将HEAD移到commit,放弃该commit之后所做的所有改变。
  • 补充提交(adding to a commit)
    git commit --amend -m "adding something to this commit"
  • 查看日志(log)
    git log查看过去所有的提交
  • 远程仓库
    git remote add origin(our name for this remote) repo-addr增加一个远程仓库
    git remote -v显示所有远程仓库
    git push -u origin master推送本地提交到origin的master分支上。
    git pull获取远程仓库上的commit changes。
    push 之后,不要再进行取消提交,补充提交,放弃提交等操作。
    已经push到远程仓库的commit是不会被改变的,虽然这些操作可以修改本地的提交历史,但是却不会改变远程仓库对应分支的提交历史。
    git clone repo-addr克隆一个远程仓库
  • 分支
    git branch branch-name创建一个新的分支,但是创建该分支后并不会切换到该分支。
    git checkout -b branch-name创建一个新的分支,并且切换到该分支。
    git branch -r列出所有远程分支
    git branch列出本地分支
    git remote show origin显示本地和远程仓库的分支信息。
    git push origin :branch_to_delete删除远程分支
    git branch -d branch_to_delete删除本地分支
    git branch -D branch_to_delete强制删除本地分支
    git remote prune origin删除远程仓库origin已经删除但是在本地还存在的分支
  • TAG
    A tag is a reference to a commit(used mostly for release versioning)
    git tag列出已有tag
    git tag -a v0.0.1添加一个tag
    git push --tags推送新加的tag
  • REBASE
    一般情况下,我们通过merge引入来源于其他分支的改动,但是merge操作会在当前分支创建merge commit节点(而且貌似会让日志变得比较乱?)。通过rebase操作,我们可以避免merge操作。
  1. 和远程分支相关的rebase:
    假设本地分支master的workflow为A–>B–>C,远程分支master的workflow为A–>D–>E,现在我们要避免merge操作而且引入远程分支的改动,那么:
    • 首先git fetch,将origin/master的改动引入到本地的origin/master分支;
    • 然后执行git rebase,此操作会将本地提交移到一个临时区域里,然后引入远程分支的提交,然后再逐个引入临时区域里的提交。引入临时区域里的提交时可能会产生冲突(比如origin/master里的提交和本地分支上的提交修改了同一个文件),此时需要像解决merge conflict一样解决冲突(编辑有冲突的文件),然后执行git addgit rebase --continue命令继续rebase过程。
  2. 和本地分支相关的rebase:
    假设本地分支master的workflow为A–>B–>C,本地分支feature的workflow为A–>D–>E,现在我们要避免merge操作而且引入master上的提交,那么可以直接checkout到feature分支上,然后git rebase master即可。但是此后master分支再要引入feature分支的提交就只有用merge操作了。
  • DIFF
    git diff比较working directory与暂存区
    git diff commit比较工作区与commit
    git diff \<commit\>..\<commit\>比较两个commit
  • 列出remote分支
    git branch -r
  • 分支重命名
    git branch -m <new-branch-name>
    git branch -m <old-branch-name> <new-branch-name>
  • 推指定commit
    git push <remote-name> <commit SHA>:<remote-branch-name>
  • 修改上游分支
    git branch -u <remote-name>/<remote-branch-name>
    git branch ---set-upstream-to=<remote-name>/<remote-branch-name>
  • 删除远程分支
    git push origin :<branch-to-delete>
  • 创建一个新的没有提交历史的分支
    git checkout --orphan <branch-name>
  • 迁移仓库
  git clone --mirror <old-repo-url>
  cd <cloned-repo>
  git push --mirror <new-repo-url>

注意’–mirror’选项clone下来的仓库里不能执行常用的’git status’这种命令,会报错“Not a git repository”,因为这样clone下来的仓库是普通的git仓库里的’.git’这种东西。’git push –mirror’这个命令也不能乱用,误用会用错误的东西覆盖服务器上的远程仓库。Reference

  • 查看日志
    git log
    git config --global color.ui true为log设置彩色显示
    git log --pretty=oneline一次提交用一行显示
    git log --pretty=format:"%h %ad %s [%an]"以指定格式输出日志
    git log --oneline -p显示每次提交的具体变更
    git log --oneline --stat
    git log --oneline --graph显示一个可视化的workflow
    git log --until=1.minute.ago显示1分钟以前的提交
    git log --since=1.day.ago显示1天之前开始的提交
    git log --since=1.month.ago --until=2.weeks.ago
    git log --since=2000-01-01 --until=2012-12-21
placeholder含义
%adauthor date
%anauthor name
%hSHA hash
%ssubject
%dref names
  • 应用patch

git apply –whitespace=fix mychanges.patch

  • cherry pick 多个提交
git cherry-pick A^..B
  • 修改指定提交
    使用git rebase -i来回退到指定commit,rebase选项里该commit使用edit选项而不是pick选项,在对该commit进行修改后用git commit --amend提交,然后继续git rebase --continue就可以了。
  • 删除分支
git branch -D xxx
  • 删除远程分支
git push origin --delete <remote-branch>
  • 只clone部分文件

通过sparseCheckout实现

  • 远程force update之后的处理

如果报错:error: cannot update the ref ‘refs/remotes/origin/majiebo/fixBug’: unable to create directory for ‘.git/logs/refs/remotes/origin/majiebo/fixBug’: No such file or directory,那么可以尝试git update-ref -d refs/remotes/origin/majiebo,参考链接:https://stackoverflow.com/a/64561177/5357784

  • 文件权限处理

https://stackoverflow.com/a/44836635/5357784
git update-index --chmod=+x <file>

  • 获取短的commit id
git rev-parse HEAD
git rev-parse --short HEAD
git log --oneline
git log --pretty=oneline --abbrev-commit
  • 重命名分支
git branch -m <old_branch> <new_branch>
  • tag

删除一个tag

git tag -d <tag_name>

删除一个remote tag

git push --delete origin <tag_name>

list tag

git tag -l