{"id":22261404,"url":"https://github.com/chenyangguang/learngit","last_synced_at":"2025-06-14T16:04:36.955Z","repository":{"id":23634082,"uuid":"27003900","full_name":"chenyangguang/learngit","owner":"chenyangguang","description":"git","archived":false,"fork":false,"pushed_at":"2019-06-28T14:21:21.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T13:46:32.172Z","etag":null,"topics":["git"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chenyangguang.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-22T16:00:42.000Z","updated_at":"2019-06-28T14:21:23.000Z","dependencies_parsed_at":"2022-08-22T03:30:45.206Z","dependency_job_id":null,"html_url":"https://github.com/chenyangguang/learngit","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/chenyangguang/learngit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenyangguang%2Flearngit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenyangguang%2Flearngit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenyangguang%2Flearngit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenyangguang%2Flearngit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chenyangguang","download_url":"https://codeload.github.com/chenyangguang/learngit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenyangguang%2Flearngit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259843315,"owners_count":22920309,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git"],"created_at":"2024-12-03T09:12:41.306Z","updated_at":"2025-06-14T16:04:36.920Z","avatar_url":"https://github.com/chenyangguang.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# git 一些经验\n\n## 入门\n\n-  初始化一个Git仓库，使用\n```\n  git init\n```\n命令。\n添加文件到Git仓库，分两步：\n第一步，使用命令git add \u003cfile\u003e，注意，可反复多次使用，添加多个文件；\n第二步，使用命令git commit，完成。\n\n## 查看变化\n\n```\ngit status \n```\n\n如果 git status 告诉你有文件被修改过，用 \n\n```\ngit diff \n```\n\n可以查看修改内容。Git鼓励大量使用分支：\n\n## 时光穿梭\n\nHEAD指向的版本就是当前版本，因此，Git允许我们在版本的历史之间穿梭，使用命令git reset --hard commit_id。\n穿梭前，用git log可以查看提交历史，以便确定要回退到哪个版本。\n要重返未来，用git reflog查看命令历史，以便确定要回到未来的哪个版本。\n\n## 基本概念\n\nGit的版本库里存了很多东西，其中最重要的就是称为stage（或者叫index）的暂存区，还有Git为我们自动创建的第一个分支master，以及指向master的一个指针叫HEAD。\ngit add命令实际上就是把要提交的所有修改放到暂存区（Stage），然后，执行git commit就可以一次性把暂存区的所有修改提交到分支\n\n## diff\n\n每次修改，如果不add到暂存区，那就不会加入到commit中\n提交后，用\n\n```\ngit diff HEAD -- readme.txt\n```\n\n命令可以查看工作区和版本库里面最新版本的区别\n\n## 切换分支 \n\n```\ngit checkout -- readme.txt\n```\n\n意思就是，把readme.txt文件在工作区的修改全部撤销，这里有两种情况：\n一种是 readme.txt 自修改后还没有被放到暂存区，现在，撤销修改就回到和版本库一模一样的状态；\n一种是 readme.txt 已经添加到暂存区后，又作了修改，现在，撤销修改就回到添加到暂存区后的状态。\n总之，就是让这个文件回到最近一次git commit或git add时的状态。\n- 场景1：当你改乱了工作区某个文件的内容，想直接丢弃工作区的修改时，用命令git checkout -- file。\n\n- 场景2：当你不但改乱了工作区某个文件的内容，还添加到了暂存区时，想丢弃修改，分两步，第一步用命令git reset HEAD file，就回到了场景1，第二步按场景1操作。\n\n##  reset\n\nGit同样告诉我们，用命令\n\n```\ngit reset HEAD file\n```\n\n可以把暂存区的修改撤销掉（unstage），重新放回工作区：\ngit reset命令既可以回退版本，也可以把暂存区的修改回退到工作区。当我们用HEAD时，表示最新的版本。\n\n## rm \n\n命令git rm用于删除一个文件。如果一个文件已经被提交到版本库，那么你永远不用担心误删，但是要小心，你只能恢复文件到最新版本，你会丢失最近一次提交后你修改的内容。\n\n## remote\n\n要关联一个远程库，使用命令\n\n```\ngit remote add origin git@server-name:path/repo-name.git；\n```\n\n关联后，使用命令\n\n```\ngit push -u origin master\n```\n\n第一次推送master分支的所有内容；\n\n此后，每次本地提交后，只要有必要，就可以使用命令\n\n```\ngit push origin master\n```\n\n推送最新修改；\n\n分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在，也就是有没有联网都可以正常工作，而SVN在没有联网的时候是拒绝干活的！当有网络的时候，再把本地提交推送一下就完成了同步，真是太方便了！\n\n## clone\n\n要克隆一个仓库，首先必须知道仓库的地址，然后使用git clone命令克隆。\n\nGit支持多种协议，包括https，但通过ssh支持的原生git协议速度最快。\n\n## ...\n\n- 查看分支：git branch\n- 创建分支：git branch \u003cname\u003e\n- 切换分支：git checkout \u003cname\u003e\n- 创建+切换分支：git checkout -b \u003cname\u003e\n- 合并某分支到当前分支：git merge \u003cname\u003e\n- 删除分支：git branch -d \u003cname\u003e\n\n## 解决冲突\n\n当Git无法自动合并分支时，就必须首先解决冲突。解决冲突后，再提交，合并完成。\n\n用\n\n```\ngit log --graph\n```\n\n命令可以看到分支合并图。\n\n## tip\n\nGit分支十分强大，在团队开发中应该充分应用。\n合并分支时，加上--no-ff参数就可以用普通模式合并，合并后的历史有分支，能看出来曾经做过合并，而fast forward合并就看不出来曾经做过合并。\n\n## stash pop\n\n修复bug时，我们会通过创建新的bug分支进行修复，然后合并，最后删除；\n\n当手头工作没有完成时，先把工作现场git stash一下，然后去修复bug，修复后，\n\n```\ngit stash pop\n```\n回到工作现场。\n\n##  ---\n\n开发一个新feature，最好新建一个分支；\n如果要丢弃一个没有被合并过的分支，可以通过git branch -D \u003cname\u003e强行删除。\n\n## 多人合作\n\n- 查看远程库信息，使用git remote -v；\n- 本地新建的分支如果不推送到远程，对其他人就是不可见的；\n- 从本地推送分支，使用git push origin branch-name，如果推送失败，先用git pull抓取远程的新提交；\n- 在本地创建和远程分支对应的分支，使用git checkout -b branch-name origin/branch-name，本地和远程分支的名称最好一致；\n\n```\ngit branch --set-upstream branch-name origin/branch-name；\n```\n\n从远程抓取分支，使用git pull，如果有冲突，要先处理冲突。\n\n## 标签\n\n命令git tag \u003cname\u003e用于新建一个标签，默认为HEAD，也可以指定一个commit id；\n\n```\ngit tag -a \u003ctagname\u003e -m \"blablabla...\"\n```\n\n可以指定标签信息；\n\n```\ngit tag -s \u003ctagname\u003e -m \"blablabla...\"\n```\n\n可以用PGP签名标签；\n\n命令git tag可以查看所有标签。\n\n## 操作标签\n\n- 命令git push origin \u003ctagname\u003e可以推送一个本地标签；\n- 命令git push origin --tags可以推送全部未推送过的本地标签；\n- 命令git tag -d \u003ctagname\u003e可以删除一个本地标签；\n- 命令git push origin :refs/tags/\u003ctagname\u003e可以删除一个远程标签。\n\n## github\n\n在 [GitHub](https://github.com)上 ，可以任意Fork开源仓库；\n自己拥有Fork后的仓库的读写权限；\n可以推送 pull request 给官方仓库来贡献代码。\n\n## 搭建 Git 服务器\n\n要方便管理公钥，用 Gitosis；\n要像 SVN那样变态地控制权限，用Gitolite。\n\n\n## 跟踪一个文件\n- git blame file 和 git log file \n会有不同。 同样是跟踪一个文件。\n\n```\ngit blame file \n```\n输入每一行最后修改的人，\n\n```\ngit log file \n```\n\n输出文件最后提交的人\n\n--------------------------------------------------------------------------------------------------\n## git 忽略文件权限修改\n\n- 针对所有git库:   \n\n```\ngit config --global core.fileMode false\n```\n\n- 针对当前库:  \n\n```\ngit config core.fileMode false\n```\n\n## 如同切换文件目录一样循环切换分支\n\n```\ngit checkout - \n```\n\n和\n\n```\ncd - \n```\n\n类似 , 会一直在上一个分支和现在的分支之间一直切换, cd - 会一直和上一个目录切换。\n\n-------------------------------------------------------------------------------------------------\n## 忽略用户名和密码push\n- ~ 目录下面，\n- touch .git-credentials 新建一个文件\n- vim .git-credentials\n- 添加 https://username:password@github.com\n- 终端配置\n\n```\ngit config --global credentials.helper store\n```\n\n## some\n\n```\ngit fsck --lost-found \ngit show hashidxxxxxx\ngit rebase hashidxxxxx \n```\n\n[参考](http://gitbook.liuhui998.com/5_9.html )\n\n## 分支重命名\n\n```\ngit branch -m old-branch-name  new-branch-name\ngit rebase master -i \n```\n\n出现多个分支的提交, 可以将那些需要合并到一个提交的commit前面的pick加改成s, 即meld的选择项, 可以在rebase过程中合并开发的过程到一个commit中, so sexy! \n\n## 批量删除本地已经合并到master的分支: \n\n```\ngit branch --merged | grep -v \"\\*\" | grep -v master | grep -v dev | xargs -n 1 git branch -d\ngit fetch --prune \u0026\u0026 git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 \u003c(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d\n```\n## 删除远程文件目录 \n\n```\ngit rm -r --cached dirname\n```\n\n比如 node_module, logs 之类无需上传的目录\n\n## worktree 问题\n+ **git worktree** 如果不小心配置启动了，会多出来两个环境变量 **GIT_WORK_TREE** 和 **GIT_DIR**, 这时候从远程拉下来的代码会一直放进一个固定的项目中。比如在 A 项目中使用 **git pull** 命令, 将有可能一直将 B 代码拉到 A 项目中， 造成 git 功能无法正常使用。\n+ **git worktree** 问题 [参考 ](https://stackoverflow.com/questions/5283262/what-is-git-work-tree-why-have-i-never-needed-to-set-this-env-var-why-now)\n\n+ **git worktree** [官方文档](https://git-scm.com/docs/git-worktree)\n\n##  短命令的三种方式\n\n\n1. 命令行直接配置\n```\n git config --global alias.co checkout\n```\n2. 或者通过设置 **~/.zshrc** 配置文件, 设置包括 git 前缀在内更短的命令.\n\n```\nalias gs='git status '\nalias ga='git add '\nalias gb='git branch '\nalias gc='git commit'\nalias gd='git diff'\n```\n3. 配置 **~/.gitconfig**, 添加至 alias 配置项， 如果没有就加上\n\n```\n[alias]\n  publish = \"!git push -u origin $(git branch-name)\"\n```\n\n + [git 教程有关短命令配置的一个文档](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases)\n\n\n\n## 命令行时间轴的精确比较\n```\ngit diff HEAD@{'2 months ago'}\n```\n## remember git username and password\n```\ngit config --global credential.helper store\ngit config --global user.name \"chenyangguang\"\ngit config --global user.password \"yourpwd\"\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchenyangguang%2Flearngit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchenyangguang%2Flearngit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchenyangguang%2Flearngit/lists"}