Git/GitHub的基本使用

发布时间:2026/9/10 22:51:29
Git/GitHub的基本使用 Git/GitHub 常用操作前言很多初学者刚接触 Git 时会把 Git 理解成“上传代码的工具”。这种理解不完全错但很容易导致后面遇到分支、冲突、远端同步、push 被拒绝、PR 合并、rebase、stash、reflog 等问题时完全不知道 Git 在做什么。更准确地说Git 是本地代码版本数据库。 GitHub 是远端 Git 仓库 Web 页面 协作平台。Git 真正重要的不是某一条命令而是它背后的模型工作区 working tree ↓ git add 暂存区 staging area / index ↓ git commit 本地仓库 local repository ↓ git push 远端仓库 remote repository例如 GitHub本文面向有一定 Linux C/C 基础、但 Git/GitHub 体系还不熟悉的开发者目标不是罗列命令而是通过一条完整学习路线建立可以支撑日常开发的 Git/GitHub 工作流。本文约定Linux 环境以 Ubuntu 24.04 为例。Windows 环境以 PowerShell 为例。远端仓库以 GitHub 为例。项目以一个简单 C 语言项目git_c_demo为练习载体。命令或参数第一次出现时会解释其功能和用途后续重复出现时不再重复解释。一、安装 Git 与基础配置在 Linux 上先检查 Git 是否已经安装git--versiongit调用 Git 程序。--version查看当前安装的 Git 版本。如果没有安装可以执行sudoaptupdatesudoaptinstallgit-ysudo以管理员权限执行命令。aptUbuntu/Debian 系统的软件包管理工具。update更新本地软件包索引。install安装软件包。-y自动回答 yes避免安装过程中反复确认。安装后配置用户名和邮箱gitconfig--globaluser.name你的名字gitconfig--globaluser.email你的邮箱git config查看或修改 Git 配置。--global设置当前用户级别的 Git 配置对当前系统用户的所有仓库生效。user.name提交记录中显示的作者名称。user.email提交记录中显示的作者邮箱。查看配置gitconfig--global--list--list列出当前配置项。注意这里的用户名和邮箱会写进 commit 作者信息里不等于 GitHub 登录账号但建议邮箱与 GitHub 账号邮箱保持一致。二、创建第一个本地 Git 仓库先创建一个 C 项目目录mkdirgit_c_democdgit_c_demomkdir创建目录。cd切换当前目录。创建一个简单的main.ccatmain.cEOF #include stdio.h int main(void) { printf(hello git\n); return 0; } EOFcat在终端打印或写入文件内容。这里配合重定向创建文件。把输出写入指定文件会覆盖原文件。EOF ... EOFHere Document用来一次性写入多行文本。创建MakefilecatMakefileEOF CC gcc CFLAGS -Wall -Wextra -g all: main main: main.c $(CC) $(CFLAGS) -o main main.c clean: rm -f main EOF测试编译make./mainmake根据Makefile中的规则执行构建。./main运行当前目录下的main可执行文件。./表示当前目录。初始化 Git 仓库gitinitgit init在当前目录创建一个新的 Git 仓库本质是生成.git目录。查看当前仓库状态gitstatusgit status查看当前分支、工作区、暂存区状态包括未跟踪文件、已修改文件、待提交内容等。这时你会看到main.c和Makefile是untracked files。untracked files表示Git 看到了这些文件 但还没有开始跟踪它们。把文件加入暂存区gitaddmain.c Makefilegit add把工作区中的修改加入暂存区。查看暂存区的文件gitls-files--cached等待下一次 commit提交到本地仓库gitcommit-m初始化 C 项目git commit把暂存区中的内容保存为一次提交。-mmessage直接在命令行指定提交说明。查看提交历史gitlog--onelinegit log查看提交历史。--oneline每个 commit 只显示一行便于快速查看。到这里最核心流程已经完成写代码 ↓ git add ↓ git commit三、理解 status、diff、log日常开发中下面三个命令使用频率非常高gitstatusgitdiffgitlog修改main.csed-is/hello git/hello git and github/main.csedLinux 下的文本处理工具。-i直接修改文件内容。s/旧内容/新内容/替换文本。查看工作区差异gitdiffgit diff查看工作区和暂存区之间的差异。简单理解就是你改了什么但还没git add。加入暂存区gitaddmain.c查看暂存区差异gitdiff--staged--staged查看暂存区和上一次提交之间的差异也就是即将被 commit 的内容。提交gitcommit-m修改 hello 输出内容查看图形历史gitlog--oneline--graph--decorate--all--graph用 ASCII 图显示分支关系。--decorate显示分支名、HEAD、tag 等引用信息。--all显示所有本地分支和远端追踪分支的历史。建议以后经常使用gitlog--oneline--graph--decorate--all它能帮助你看清楚当前仓库的真实历史结构。四、撤销错误操作restore、reset、revert 的基本思想Git 里“撤销”不是一个命令解决所有问题而是要先判断你要撤销的是哪一层工作区修改 暂存区修改 已经 commit 的修改撤销工作区修改gitrestore main.cgit restore恢复工作区文件内容。常用于撤销还没有加入暂存区的修改。如果文件已经git add到暂存区先撤出暂存区gitrestore--stagedmain.c--staged只把文件从暂存区移回工作区不删除实际修改。如果 commit 已经提交而且希望用一个新的提交来抵消它可以使用gitrevertcommit_hashgit revert创建一个新的 commit用来反向撤销指定 commit 的修改。commit_hash某次提交的编号。revert的特点是安全因为它不删除历史而是新增一条“反向修改”。日常建议未 addgit restore 已 add 未 commitgit restore --staged 已 commit 且已共享优先 git revert五、分支branch、switch、merge分支是 Git 的核心能力之一。查看当前分支gitbranchgit branch查看、创建或删除本地分支。创建并切换新分支gitswitch-cfeature/demogit switch切换分支。-ccreate创建新分支并切换过去。feature/demo分支名。切换回 maingitswitch main在 feature 分支提交后可以合并回 maingitmerge feature/demogit merge把指定分支的修改合并到当前分支。删除已合并分支gitbranch-dfeature/demo-ddelete安全删除本地分支。如果 Git 认为该分支未合并会拒绝删除。分支的基本模型是main | A \ B feature/demo合并后可能变成A --- B main或者产生 merge commitA ---- M main \ / B --六、冲突两个分支改了同一处代码怎么办冲突的本质是两个分支改了同一个位置 Git 不知道最终应该保留哪一个版本。例如HEADprintf(hello from main branch\n);printf(hello from feature branch\n);feature/demo含义是 HEAD 到 当前分支的内容。 到 要合并进来的分支内容。解决冲突的标准流程gitstatuscatmain.cnanomain.cgitaddmain.cgitcommitnanoLinux 下常见的终端文本编辑器。不带-m的git commit打开编辑器填写提交信息常用于 merge commit。解决冲突时必须删除 最终文件应该是干净、可编译的代码。冲突不是错误而是 Git 在告诉你我不能替你决定最终代码应该是什么 需要你自己判断。七、GitHub远端仓库与 SSH 连接GitHub 可以理解成GitHub 远端 Git 仓库 Web 页面 协作工具它不仅能保存代码还能支持README Issues Pull Request Actions Releases WikiLinux 开发中推荐使用 SSH 连接 GitHub。检查 SSH 目录ls-al~/.sshls列出目录内容。-a显示隐藏文件。-l使用长格式显示文件详细信息。~/.ssh当前用户的 SSH 配置目录。生成 SSH keyssh-keygen-ted25519-C你的邮箱ssh-keygen生成 SSH 密钥。-t指定密钥类型。ed25519一种现代 SSH 密钥算法。-C添加注释通常写邮箱方便识别密钥用途。启动 ssh-agenteval$(ssh-agent-s)eval执行字符串中的命令。ssh-agent -s启动 SSH agent并输出可被 shell 执行的环境变量设置。添加私钥ssh-add ~/.ssh/id_ed25519ssh-add把私钥加入 ssh-agent避免每次连接都手动指定。查看公钥cat~/.ssh/id_ed25519.pub只复制.pub公钥到 GitHub不要复制没有.pub的私钥文件。测试连接ssh-Tgitgithub.comssh通过 SSH 协议连接远程主机。-T不分配远程终端只测试认证连接。gitgithub.comGitHub SSH 连接地址。成功时通常会看到Hi 用户名! Youve successfully authenticated...八、本地仓库连接 GitHubremote、push、origin/main如果本地已经有仓库GitHub 上创建了空仓库可以添加远端gitremoteaddorigin gitgithub.com:用户名/git_c_demo.gitgit remote管理远端仓库。add添加远端。origin远端仓库别名约定俗成常用这个名字。gitgithub.com:用户名/仓库名.gitSSH 格式的远端仓库地址。查看远端配置gitremote-v-vverbose显示详细远端地址包括 fetch 和 push 地址。第一次推送 maingitpush-uorigin maingit push把本地提交推送到远端仓库。-u建立 upstream 追踪关系。origin远端仓库名。main要推送的本地分支名。执行后建立关系本地 main ←→ 远端 origin/main这里要区分main 本地分支。 origin/main 本地记录的远端 origin 上 main 分支的状态。 它不是 GitHub 本身而是本地保存的一份远端分支快照。如果远端地址写错可以修改gitremote set-url origin gitgithub.com:用户名/git_c_demo.gitset-url修改已有远端的 URL 地址。九、clone第二台电脑如何接入项目如果 Windows 主机要接入同一个 GitHub 仓库应使用git clone gitgithub.com:用户名/git_c_demo.gitgit clone复制一个已有 Git 仓库到本地包括代码、.git目录、提交历史、分支、远端配置等。注意clone 不是下载源码。 clone 是复制整个 Git 仓库。所以 clone 后不需要 git init。 不需要 git remote add origin。因为 clone 已经自动完成了创建 .git 复制历史 设置 origin 检出默认分支 main 建立 upstreamWindows 上建议使用 PowerShellmkdir D:\GitStudy cd D:\GitStudy git clone gitgithub.com:用户名/git_c_demo.git cd git_c_demo git statusWindows 下查看文件dirdirPowerShell/CMD 下查看当前目录文件列表。查看文件内容Get-Contentmain.cGet-ContentPowerShell 下读取并打印文件内容。打开文本文件notepad main.cnotepad打开 Windows 记事本编辑文件。十、双机协作fetch 和 pull典型环境是Ubuntu 24.04 虚拟机 │ │ git push ▼ GitHub ▲ │ git fetch / git pull Windows 主机一台机器 push 后另一台机器不会自动变化。在另一台机器上可以先执行git fetchgit fetch从远端获取最新提交、分支、标签等信息更新origin/main但不修改当前本地分支和工作区文件。fetch 后查看历史git log--oneline--graph--decorate--all你可能看到origin/main 已经前进 HEAD - main 还停在旧提交如果要真正同步当前分支git pullgit pull从远端拉取并合并到当前分支。简单理解git pull git fetch git merge更稳妥的习惯是git fetch git log--oneline--graph--decorate--all gitdiffmain origin/main git pullgit diff main origin/main比较本地main和远端追踪分支origin/main的差异。十一、push 被拒绝non-fast-forward双机协作或多人协作时经常会遇到! [rejected] main - main (fetch first) error: failed to push some refs Updates were rejected because the remote contains work that you do not have locally.意思是远端有你本地没有的提交。 GitHub 拒绝你的 push防止你覆盖远端历史。安全处理流程git fetch git log--oneline--graph--decorate--all git pull git push如果 pull 过程中冲突就按冲突流程解决git statusGet-Contentmain.c notepad main.c git add main.c git commit git push不要一看到 push 被拒绝就执行gitpush-f-fforce强制推送。它可能覆盖远端已有提交团队开发中非常危险。十二、GitHub Pull Request 工作流真实团队开发通常不直接往main推代码而是main 保持稳定 feature 分支开发 Pull Request 合并标准流程gitswitchmain git pull gitswitch-c feature/pr-demo notepad main.c gitdiffgit add main.c git commit-m演示 Pull Request 工作流git push-u origin feature/pr-demo然后在 GitHub 网页上Pull requests ↓ New pull request ↓ base: main compare: feature/pr-demo ↓ Create pull request术语解释Pull Request GitHub 上的合并请求用来请求把某个分支的修改合并到目标分支。 base 目标分支通常是 main。 compare 要合并进来的分支通常是 feature 分支。PR 页面重点看Conversation 讨论区。 Commits 这个 PR 包含哪些提交。 Files changed 这个 PR 修改了哪些文件和哪些行。 Checks 自动检查结果例如测试、编译、代码扫描。确认没问题后Merge pull request Confirm merge Delete branchPR 合并发生在 GitHub 上但本地不会自动更新所以还要gitswitchmain git pull git branch-d feature/pr-demo十三、PR 后续修改与 Code Review真实开发中PR 很少一次就合并。常见流程是创建 PR ↓ review 提意见 ↓ 本地继续改 ↓ commit push 到同一个 feature 分支 ↓ 原 PR 自动更新Code Review 是合并前的代码检查和讨论过程。常见动作包括Comment 只发表评论。 Approve 批准 PR。 Request changes 请求修改暂时不建议合并。关键点PR 跟踪的是 compare 分支不是某一次 commit。所以如果你已经创建了feature/review-demo的 PR后续只需要继续在这个分支上修改git branch notepad main.c gitdiffgit add main.c git commit-m根据 review 修改输出内容git pushGitHub 上原来的 PR 会自动更新不需要重新创建 PR。十四、stash临时保存做到一半的工作日常开发中经常会出现代码写到一半还不能 commit 但突然需要切回 main 处理别的任务。这时使用 stash。git stash push-m临时保存当前修改git stash管理临时保存的修改。push把当前未提交修改压入 stash 栈。这里的 push 不是推送到 GitHub。-mmessage给这次 stash 添加说明。查看 stash 列表git stash listlist列出当前仓库中的 stash 记录。恢复 stashgit stash apply stash{0}apply把指定 stash 的内容恢复到当前工作区但保留 stash 记录。stash{0}最新的一条 stash 记录。删除 stashgit stash drop stash{0}drop删除指定 stash 记录。更快捷的方式git stash poppop恢复最新 stash并在恢复成功后删除这条 stash。如果新建了未跟踪文件也想一起 stashgit stash push-u-m保存包括新文件的修改-uinclude untracked把未跟踪文件也一起保存进 stash。注意stash 是本地操作。 不会 push 到 GitHub。 Windows 的 stashUbuntu 看不到。十五、rebase让 feature 分支基于最新 main当你从main创建 feature 分支后别人又往main合并了新代码你的 feature 分支就落后了。这时有两种方式merge main 到 feature rebase feature 到最新 main 后面基础 rebase 用法gitswitchmain git pull gitswitchfeature/rebase-demo git rebase maingit rebase把当前分支上的提交重新应用到另一个分支后面。main这里表示把当前 feature 分支的提交重新放到最新main后面。rebase 前F feature / A --- M mainrebase 后A --- M --- F feature | main注意F会变成Fcommit hash 可能变化。commit hash每个 commit 的唯一编号。提交内容、父提交、作者信息或时间变化时hash 通常也会变化。如果 rebase 过程中冲突git status notepad 冲突文件 git add 冲突文件 git rebase--continue--continue解决冲突并git add后继续执行被暂停的 rebase。如果状态混乱git rebase--abort--abort取消当前 rebase恢复到 rebase 开始前的状态。安全原则自己的本地 feature 分支可以 rebase。 main 分支不要随便 rebase。 已经共享给别人的分支不要随便 rebase。十六、.gitignore已经被跟踪的文件为什么 ignore 不掉.gitignore的核心规则是.gitignore 只影响未跟踪文件。如果一个文件已经被git add/git commit过它已经是 tracked file。之后即使写进.gitignoreGit 也会继续跟踪它。判断文件是否被 Git 跟踪gitls-files local_config.txtgit ls-files列出 Git 当前正在跟踪的文件。后面跟文件名时用来判断该文件是否在跟踪列表中。让 Git 停止跟踪文件但保留本地文件gitrm--cached local_config.txtgit rm让 Git 删除某个文件。--cached只从 Git 的索引/跟踪列表中移除不删除工作区真实文件。如果是目录gitrm-r--cached build/-rrecursive递归处理目录中的所有文件。查看被忽略文件git status--ignored--ignored让git status额外显示被.gitignore忽略的文件。C/C 项目常见.gitignore# object files *.o *.out *.a *.so *.exe # executable main # build directories build/ cmake-build-*/ # debug/core/log core core.* *.log # editor .vscode/ .idea/ *.swp # local config local_config.txt通常应该提交.c / .h / .cpp / .hpp Makefile CMakeLists.txt README.md .gitignore 测试代码 必要脚本通常不应该提交.o 文件 可执行文件 build 目录 core dump 日志文件 本地配置 IDE 个人配置 临时测试文件十七、reflog误操作后的救命记录如果你 reset 错了或者发现 commit “不见了”先不要慌。执行git refloggit reflog查看本地 HEAD 或分支引用的移动记录常用于找回 reset、rebase、切分支等操作后“看起来丢失”的提交。git log和git reflog的区别git log 查看当前分支能访问到的提交历史。 git reflog 查看 HEAD 和分支指针最近移动过的位置。模拟回退git reset--hard HEAD~1git reset移动当前分支指针让当前分支回到指定 commit。--hard让当前分支、暂存区、工作区都恢复到指定 commit会丢弃未提交修改危险。HEAD~1当前 HEAD 的上一个提交。如果 reflog 里看到abc1234 HEAD{1}: commit: 添加 reflog 演示提交可以恢复git reset--hard abc1234abc1234目标 commit hash要换成你自己终端里看到的编号。注意reflog 是本地记录。 不会 push 到 GitHub。 Windows 的 reflogUbuntu 看不到。如果你只是演示分支想强制删除git branch-D feature/reflog-demo-D强制删除本地分支即使它没有合并到 main也会删除。比-d危险。十八、日常开发推荐流程1. 开始一个新功能gitswitchmain git pull gitswitch-c feature/功能名2. 开发并提交git status gitdiffgit add 具体文件 gitdiff--staged git commit-m清晰说明修改3. 推送 feature 分支git push-u origin feature/功能名4. GitHub 上创建 PRPull requests ↓ New pull request ↓ base: main compare: feature/功能名 ↓ Create pull request5. 根据 review 修改gitdiffgit add 具体文件 git commit-m根据 review 修改代码git push6. PR 合并后本地收尾gitswitchmain git pull git branch-d feature/功能名7. 另一台机器同步gitswitch maingitpullgitstatus这就是日常开发最常用的 GitHub Flow。十九、常见问题处理流程1. push 被拒绝git fetch git log--oneline--graph--decorate--all git pull git push不要直接git push -f。2. 发生冲突git statusGet-Content冲突文件 notepad 冲突文件 git add 冲突文件 git commit整理文件时删除 3. 代码写到一半要切任务git stash push-u-m说明当前临时工作gitswitchmain git pull恢复gitswitchfeature/原来的分支 git stash list git stash apply stash{0}git stash drop stash{0}4. feature 分支落后 maingitswitchmain git pull gitswitchfeature/功能名 git rebase main如果冲突git status notepad 冲突文件 git add 冲突文件 git rebase--continue5. .gitignore 不生效gitls-files 文件名 gitrm--cached 文件名 git add.gitignore git commit-m停止跟踪本地文件6. commit 看起来丢了git status git reflog git reset--hard commit_hash不确定时不要继续乱操作先保存git status、git log、git reflog的输出。二十、危险命令清单这些命令不是不能用而是必须知道风险。gitreset--hard危险点会丢弃未提交的工作区和暂存区修改。gitpush-f危险点会强制覆盖远端历史可能删除别人已经 push 的提交。gitbranch-D分支名危险点会强制删除本地分支即使它没有合并。gitrm文件名危险点会从 Git 跟踪中删除文件也会删除工作区真实文件。相对安全版本是gitrm--cached文件名它只停止跟踪保留本地文件。总结完成上述全部内容已经足够满足日常开发。上述内容总结如下1. 创建仓库。 2. 提交代码。 3. 查看修改。 4. 创建分支。 5. 合并分支。 6. 解决冲突。 7. 推送到 GitHub。 8. 克隆仓库。 9. 双机同步。 10. 处理 push 被拒绝。 11. 使用 Pull Request。 12. 根据 Code Review 继续修改。 13. 使用 stash 临时保存。 14. 使用 rebase 让 feature 基于最新 main。 15. 正确处理 .gitignore。 16. 使用 reflog 找回误操作后的提交。这些能力已经能支撑个人项目 课程项目 实验室代码管理 GitHub 开源项目基础协作 公司中普通 feature 分支开发进阶部分下面这些内容在本文中未曾涉及读者若有需要可以等真实遇到场景再学cherry-pick interactive rebase squash submodule Git LFS bisect worktree GitHub Actions Git 内部对象 blob / tree / commit / tag 复杂 release 流程对于刚接触 Git 的开发者最重要的不是继续堆命令而是把下面这条主线用熟main 拉新 feature 开发 commit 保存 push 远端 PR 合并 pull 同步 stash 临时切任务 rebase 跟上 main reflog 处理误操作 .gitignore 管理无关文件结语Git 真正难的地方不是记命令而是理解每条命令在改变什么它改的是工作区 它改的是暂存区 它创建了 commit 它移动了分支指针 它同步了远端 它重写了历史 它只是本地操作还是会影响 GitHub使用 Git 的最重要的习惯提交前看 git status。 提交前看 git diff。 不要提交编译产物和本地配置。 新功能从 feature 分支开始。 合并用 PR。 出错先看状态不要乱用危险命令。以上就是本文全部内容