Sempena ulang tahun Git yang ke-13, berikut ialah 13 petua dan kiat untuk menjadikan pengalaman Git anda lebih berguna dan berkuasa. Mulakan dengan beberapa asas yang mungkin anda terlepas pandang dan kembangkan kepada beberapa petua pengguna yang berkuasa sebenar!
Apabila anda mula-mula cuba menggunakan arahan git untuk melakukan perubahan pada repositori, anda mungkin menerima mesej alu-aluan seperti ini:
*** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity.
Anda mungkin tidak menyedari bahawa arahan inilah yang mengubah suai kandungan ~/.gitconfig, di mana Git menyimpan pilihan konfigurasi global. Anda boleh melakukan banyak perkara dengan fail ~/.gitconfig, termasuk mentakrifkan alias, menghidupkan (atau mematikan) pilihan arahan khusus secara kekal dan mengubah suai cara Git berfungsi (contohnya, algoritma diff yang digunakan git diff, atau jenis apa of diff digunakan secara lalai strategi gabungan). Anda juga boleh memasukkan fail konfigurasi lain secara bersyarat berdasarkan laluan ke repositori! Lihat man git-config untuk semua butiran.
Dalam petua sebelumnya, anda mungkin tertanya-tanya apakah yang dilakukan oleh --global flag dalam arahan git config. Ia memberitahu Git untuk mengemas kini konfigurasi "global" dalam ~/.gitconfig. Sudah tentu, mempunyai konfigurasi global juga bermakna akan ada konfigurasi setempat Jelas sekali, jika anda meninggalkan --global flag, git config sebaliknya akan mengemas kini konfigurasi khusus repositori, yang disimpan dalam .git/config.
Pilihan yang ditetapkan dalam fail .git/config akan mengatasi semua tetapan dalam fail ~/.gitconfig. Jadi, sebagai contoh, jika anda perlu menggunakan alamat e-mel yang berbeza untuk repositori tertentu, anda boleh menjalankan git config user.email "also_you@example.com". Sebarang komitmen dalam repositori itu kemudiannya akan menggunakan alamat e-mel anda yang dikonfigurasikan secara individu. Ini berguna jika anda bekerja pada projek sumber terbuka dan mahu mereka memaparkan alamat e-mel mereka sendiri semasa masih menggunakan e-mel kerja anda sebagai konfigurasi Git utama anda.
Hampir semua yang anda boleh tetapkan dalam ~/.gitconfig, anda juga boleh tetapkan dalam .git/config untuk menjadikannya berfungsi pada repositori tertentu. Dalam petua di bawah, apabila saya menyebut menambah sesuatu pada ~/.gitconfig , cuma ingat bahawa anda juga boleh menambah .git/config untuk repositori tertentu untuk menetapkan pilihan itu.
Anda boleh menggunakan arahan git config untuk mentakrifkan alias - contohnya, menjalankan git config --global --add alias.st status akan membuat running git st melakukan perkara yang sama seperti menjalankan git status - tetapi saya dapati semasa menentukan alias, Biasanya lebih mudah untuk mengedit fail ~/.gitconfig secara terus.
Jika anda memilih untuk menggunakan kaedah ini, anda akan mendapati bahawa fail ~/.gitconfig ialah fail INI. INI ialah format fail nilai kunci dengan perenggan tertentu. Apabila menambah alias, anda akan menukar perenggan [alias]. Sebagai contoh, apabila mentakrifkan alias git st yang sama di atas, tambahkan yang berikut pada fail:
[alias] st = status
(Jika anda sudah mempunyai perenggan [alias], tambahkan sahaja baris kedua pada bahagian yang sedia ada.)
4. Alias dalam arahan shell别名不仅仅限于运行其他 Git 子命令 —— 你还可以定义运行其他 shell 命令的别名。这是一个用来处理一个反复发生的、罕见和复杂的任务的很好方式:一旦你确定了如何完成它,就可以在别名下保存该命令。例如,我有一些复刻的开源项目的仓库,并进行了一些本地修改。我想跟上项目正在进行的开发工作,并保存我本地的变化。为了实现这个目标,我需要定期将来自上游仓库的更改合并到我复刻的项目中 —— 我通过使用我称之为upstream-merge 的别名来完成。它是这样定义的:
upstream-merge = !"git fetch origin -v && git fetch upstream -v && git merge upstream/master && git push"
别名定义开头的 ! 告诉 Git 通过 shell 运行这个命令。这个例子涉及到运行一些 git 命令,但是以这种方式定义的别名可以运行任何 shell 命令。
(注意,如果你想复制我的 upstream-merge 别名,你需要确保你有一个名为 upstream 的 Git 远程仓库,指向你已经分配的上游仓库,你可以通过运行 git remote add upstream
如果你在一个有很多分支活动的项目上开发,有时可能很难掌握所有正在发生的工作以及它们之间的相关性。各种图形用户界面工具可让你获取不同分支的图片并在所谓的“提交图表”中提交。例如,以下是我使用 GitLab提交图表查看器可视化的我的一个仓库的一部分:
GitLab commit graph viewer
如果你是一个专注于命令行的用户或者发现分支切换工具让人分心,那么可以从命令行获得类似的提交视图。这就是 git log 命令的 --graph 参数出现的地方:
Repository visualized with --graph command
以下命令可视化相同仓库可达到相同效果:
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)%Creset' --abbrev-commit --date=relative
--graph 选项将图添加到日志的左侧,--abbrev-commit 缩短提交的 SHA 值,--date=relative 以相对方式表示日期,以及 --pretty 来处理所有其他自定义格式。我有个 git lg 别名用于这个功能,它是我最常用的 10 个命令之一。
有时,你越是想避开越避不开,你会发现你需要运行 git push --force 来覆盖仓库远程副本上的历史记录。你可能得到了一些反馈,需要你进行交互式变基,或者你可能已经搞砸了,并希望隐藏“罪证”。
当其他人在仓库的远程副本的同一分支上进行更改时,会发生强制推送的危险。当你强制推送已重写的历史记录时,这些提交将会丢失。这就是 git push --force-with-lease 出现的原因 -- 如果远程分支已经更新,它不会允许你强制推送,这确保你不会丢掉别人的工作。
你是否使用过 git commit -a 在一次行动中提交所有未完成的修改,但在你推送完提交后才发现 git commit -a 忽略了新添加的文件?你可以使用 git add -N (想想 “notify”) 来解决这个问题,告诉 Git 在第一次实际提交它们之前,你希望在提交中包含新增文件。
A best practice when using Git is to ensure that each commit contains only one logical change - whether that's fixing a bug or adding new functionality. However, sometimes when you're working, changes in your repository should end up using multiple commits. How can you manage to separate things so that each commit contains only the appropriate changes? git add --patch is here to save you!
This flag will cause the git add command to look at all changes in your working copy and ask for each change if you want to commit it, skip it, or defer the decision (you can select ? after running the command to see other more powerful options). git add -p is a great tool for producing well-structured commits.
Similar to git add -p, the git checkout command also accepts the --patch or -p option, which will cause it to display each "chunk" of changes in the local working copy and allow it to be discarded - in simple terms Restore the local working copy to its state before the changes.
This is really great. For example, when you are tracking a bug that introduces a bunch of debug log statements, after fixing the bug, you can first use git checkout -p to remove all new debug logs, and then git add -p to add the bug fix. There's nothing more satisfying than putting together an elegant, well-structured submission!
Some projects have a rule that every commit in the repository must be in a working state - that is, on every commit, the code should be able to compile, or the test suite should be run without failure. This isn't difficult when you're working on a branch, but if you end up needing to rebase for some reason, then you'll need to step through each rebased commit to make sure you don't accidentally introduce a break , and this process is tedious.
Fortunately, git rebase already overrides the -x or --exec option. git rebase -x
Many Git subcommands accept a revision parameter to determine which part of the repository the command acts on, which can be the SHA1 value of a specific commit, the name of a branch, or even a symbolic name such as HEAD (representing the current checkout branch's last commit), in addition to these simple forms, you can also append a specified date or time as a parameter, indicating "a reference to this time".
This feature will become very useful at some point. When you deal with the latest bug and say to yourself: "This function was fine yesterday, what has been changed?" Instead of staring at the full screen of git log output trying to figure out when the commit was changed, you Just run git diff HEAD@{yesterday} to see all modifications since yesterday. This also works for longer time periods (e.g. git diff HEAD@{'2 months ago'}), as well as an exact date (e.g. git diff HEAD@{'2010-01-01 12:00:00'}) .
You can also use these date-based revision parameters with any Git subcommand that uses revision parameters. There are details on exactly which format to use in the gitrevisions man page.
Have you ever tried to kill a commit during a rebase, and then found that you needed to keep something in that commit? You may feel that this information can never be retrieved and can only be recreated. But if you commit in your local working copy, the commit will be added to the reflog and you can still access it.
Running git reflog will display a list of all activity for the current branch in your local working copy and give you the SHA1 value of each commit. Once you find the commit you abandoned when rebasing, you can run git checkout
Ouch! It turns out that my basic math skills are inferior to my Git skills. Git was originally released in 2005, which means it will turn 13 this year instead of 12. To make up for that mistake, here’s tip number 13 that can turn us into thirteen.
If you use a branch-based workflow, as you work on a long-term project, unless you clean up each branch as it is merged, you will end up with a bunch of branches. This makes it difficult to find the branch you want, and the forest of branches makes it impossible to find it. Even worse, if you have a large number of active branches, determining whether a branch is merged (can be safely deleted) or is still not merged and should be left alone can be very tedious. Fortunately, Git can help you: Just run git branch --merged to get a list of branches that have been merged into your current branch, or git branch --no-merged to find out which branches have been merged into other branches. . By default this will list branches in your local working copy, but if you include the --remote or -r argument on the command line, it will also list merged branches that only exist in the remote repository.
Important: If you plan to use the output of git branch --merged to clean up branches that have been merged, you need to be careful that its output also includes the current branch (after all, this current branch is merged into the current branch!). Make sure you exclude the branch before any destruction (if you forget, see tip 12 to learn how reflog can help you get the branch back, hope it helps...).
Hopefully at least one of these tips taught you something new about Git, which is a 13-year-old project that continues to innovate and add new features. What's your favorite Git trick?
The above is the detailed content of 13 Practical Git Tips. For more information, please follow other related articles on the PHP Chinese website!