Git/hacks: Difference between revisions
add clone singe branch example |
m Text replacement - "<(\/?)source" to "<$1syntaxhighlight" |
||
| Line 1: | Line 1: | ||
==Search== | ==Search== | ||
<code>git grep</code> only works on the current content of your working copy. To search through all revisions, you can use something like | <code>git grep</code> only works on the current content of your working copy. To search through all revisions, you can use something like | ||
< | <syntaxhighlight lang="bash"> | ||
# -F is --fixed-strings | # -F is --fixed-strings | ||
# Interpret PATTERN as a list of fixed strings (instead of regular expressions), separated by newlines, any of which is to be matched. | # Interpret PATTERN as a list of fixed strings (instead of regular expressions), separated by newlines, any of which is to be matched. | ||
git rev-list --all | ( while read revision; do git grep -F 'wgAWSCredentials' $revision; done; ) | git rev-list --all | ( while read revision; do git grep -F 'wgAWSCredentials' $revision; done; ) | ||
</ | </syntaxhighlight>You can also search with <code>git log</code> to find commits of interest. Simply use the <code>--grep</code> option and add the <code>-i</code> option (short for <code>--regexp-ignore-case</code>) to make your pattern case-insensitive. Adding <code>--reverse</code> will show commits ordered from the beginning of time - so finding the earliest commit first. | ||
<code>git log --reverse --grep rocky -i</code> | <code>git log --reverse --grep rocky -i</code> | ||
| Line 26: | Line 26: | ||
==Ignore File Mode== | ==Ignore File Mode== | ||
Sometimes you have to temporarily change file modes (or some script might alter your working directory). Anyway, to ignore file mode changes temporarily, you can just add <code>-c core.fileMode=false</code> to your command. E.g.: | Sometimes you have to temporarily change file modes (or some script might alter your working directory). Anyway, to ignore file mode changes temporarily, you can just add <code>-c core.fileMode=false</code> to your command. E.g.: | ||
< | <syntaxhighlight lang="bash"> | ||
git -c core.fileMode=false status | git -c core.fileMode=false status | ||
</ | </syntaxhighlight> | ||
You can also put this into a repo or global config, but you probably shouldn't. | You can also put this into a repo or global config, but you probably shouldn't. | ||
If you need to change filemodes back to the way they were in the repo, you can do something like | If you need to change filemodes back to the way they were in the repo, you can do something like | ||
< | <syntaxhighlight lang="bash"> | ||
git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7 | xargs chmod +x | git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7 | xargs chmod +x | ||
git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7 | xargs chmod -x | git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7 | xargs chmod -x | ||
</ | </syntaxhighlight> | ||
==Working on a remote terminal== | ==Working on a remote terminal== | ||
If you're working on a remote terminal and your repository get's complicated, but you don't have desktop tools like [[meld]] or [[gitk]] to look at it, you can copy the remote repo to your desktop with <code>rsync</code>, even if you have to jump through a bastion host with something like: | If you're working on a remote terminal and your repository get's complicated, but you don't have desktop tools like [[meld]] or [[gitk]] to look at it, you can copy the remote repo to your desktop with <code>rsync</code>, even if you have to jump through a bastion host with something like: | ||
< | <syntaxhighlight lang="bash"> | ||
rsync -e "ssh -t bastion ssh -A" -ravz centos@10.0.50.68:/opt/meza/ ./meza-es1/ | rsync -e "ssh -t bastion ssh -A" -ravz centos@10.0.50.68:/opt/meza/ ./meza-es1/ | ||
</ | </syntaxhighlight> | ||
If that complains about host-key verification, then simply do an SSH first to the host, accept the host key identity, and logout. Now the rsync will work because the host-key is already accepted as valid. | If that complains about host-key verification, then simply do an SSH first to the host, accept the host key identity, and logout. Now the rsync will work because the host-key is already accepted as valid. | ||
| Line 53: | Line 53: | ||
Add <code>GIT_TRACE=1</code> to your command to see more of what's going on. (Note that there are no spaces and no semicolon.) | Add <code>GIT_TRACE=1</code> to your command to see more of what's going on. (Note that there are no spaces and no semicolon.) | ||
< | <syntaxhighlight lang="bash"> | ||
GIT_TRACE=1 git status | GIT_TRACE=1 git status | ||
</ | </syntaxhighlight> | ||
==Just the facts== | ==Just the facts== | ||
| Line 63: | Line 63: | ||
See all the changes in color, but without any context lines, and without the leading +/-/<nowiki>[space]</nowiki> | See all the changes in color, but without any context lines, and without the leading +/-/<nowiki>[space]</nowiki> | ||
This makes it easy to grab changes and stuff them in another file for example. | This makes it easy to grab changes and stuff them in another file for example. | ||
< | <syntaxhighlight lang="bash"> | ||
git diff -U0 --color myfile | sed -r "s/^([^-+ ]*)[-+ ]/\\1/" | git diff -U0 --color myfile | sed -r "s/^([^-+ ]*)[-+ ]/\\1/" | ||
</ | </syntaxhighlight> | ||
==What is this miscellaneous file, and how does it compare to what's in my repo?== | ==What is this miscellaneous file, and how does it compare to what's in my repo?== | ||
Say you've got a config file lying around (untracked) in your local working tree. It's not in your current project branch, but you know it's an important file. How does it compare to what's in the '''freephile''' remote, '''es128''' branch version of the file? | Say you've got a config file lying around (untracked) in your local working tree. It's not in your current project branch, but you know it's an important file. How does it compare to what's in the '''freephile''' remote, '''es128''' branch version of the file? | ||
< | <syntaxhighlight lang="bash"> | ||
git diff freephile/es128:config/core/MezaLocalExtensions.yml config/core/MezaLocalExtensions.yml | git diff freephile/es128:config/core/MezaLocalExtensions.yml config/core/MezaLocalExtensions.yml | ||
</ | </syntaxhighlight> | ||
==How has this file changed over time?== | ==How has this file changed over time?== | ||
| Line 81: | Line 81: | ||
Do you think a particular file has changed between two separate feature branches (ea based off master)? | Do you think a particular file has changed between two separate feature branches (ea based off master)? | ||
< | <syntaxhighlight lang="bash"> | ||
# git diff branch1..branch2 -- path/to/file | # git diff branch1..branch2 -- path/to/file | ||
git diff es128-rebased..get-to-know-meza -- manual/commands.md | git diff es128-rebased..get-to-know-meza -- manual/commands.md | ||
</ | </syntaxhighlight> | ||
==Add that forgotten file== | ==Add that forgotten file== | ||
You forgot to add a file to the last commit? Just add it to the index, and commit with <code>--amend</code>. Added a file that shouldn't be there? <code>git rm</code> it. If you leave off the -m (message) option in the new commit, it will let you re-use the last commit message. This lets you "undo the last commit" and redo it right. You usually do not want to amend a commit if you've already pushed it to other repos, but if it's just local <code>--amend</code> is awesome-sauce. | You forgot to add a file to the last commit? Just add it to the index, and commit with <code>--amend</code>. Added a file that shouldn't be there? <code>git rm</code> it. If you leave off the -m (message) option in the new commit, it will let you re-use the last commit message. This lets you "undo the last commit" and redo it right. You usually do not want to amend a commit if you've already pushed it to other repos, but if it's just local <code>--amend</code> is awesome-sauce. | ||
< | <syntaxhighlight lang="bash"> | ||
git add forgotten.php | git add forgotten.php | ||
git rm oops.txt | git rm oops.txt | ||
git commit --amend | git commit --amend | ||
git log --stat | git log --stat | ||
</ | </syntaxhighlight> | ||
==Undo a commit== | ==Undo a commit== | ||
Sometimes a commit is just wrong or 'breaks the build' so to speak. If you really just want to '''undo''' a commit, then | Sometimes a commit is just wrong or 'breaks the build' so to speak. If you really just want to '''undo''' a commit, then | ||
< | <syntaxhighlight lang="bash"> | ||
# view what changes were made in the last commit | # view what changes were made in the last commit | ||
git difftool HEAD~ | git difftool HEAD~ | ||
| Line 106: | Line 106: | ||
# reset --hard will undo the last commit, and discard any changes that were made in the commit. Your work tree will be identical to the way it was after the prior commit. | # reset --hard will undo the last commit, and discard any changes that were made in the commit. Your work tree will be identical to the way it was after the prior commit. | ||
git reset --hard HEAD~ | git reset --hard HEAD~ | ||
</ | </syntaxhighlight> | ||
Using <code>reset</code> you can even go backwards several commits if you want. | Using <code>reset</code> you can even go backwards several commits if you want. | ||
The entire internet tells you not to <code>reset</code> if you've already pushed. But if you're just pushing (from machine A: your desktop) to a remote (machine B: eg. GitHub) so that you can then pull those changes into another space (machine C: development/staging/production/other machine) you can push your changes with <code>--force</code>; and pull them from that other environment. It may be quicker and easier though to identify the SHA of the n-1 commit and then <code>reset</code> on machine C | The entire internet tells you not to <code>reset</code> if you've already pushed. But if you're just pushing (from machine A: your desktop) to a remote (machine B: eg. GitHub) so that you can then pull those changes into another space (machine C: development/staging/production/other machine) you can push your changes with <code>--force</code>; and pull them from that other environment. It may be quicker and easier though to identify the SHA of the n-1 commit and then <code>reset</code> on machine C | ||
< | <syntaxhighlight lang="bash"> | ||
git log -n 4 | git log -n 4 | ||
# find the commit SHA, and use it on machine C | # find the commit SHA, and use it on machine C | ||
git reset --hard d89c004cfe4bd67838fb41c7a6644bb15feee5cc | git reset --hard d89c004cfe4bd67838fb41c7a6644bb15feee5cc | ||
</ | </syntaxhighlight> | ||
Credit: there's a clear explanation at https://www.git-tower.com/learn/git/faq/undo-last-commit | Credit: there's a clear explanation at https://www.git-tower.com/learn/git/faq/undo-last-commit | ||
| Line 220: | Line 220: | ||
==Delete local and remote merged branches== | ==Delete local and remote merged branches== | ||
< | <syntaxhighlight lang="bash"> | ||
git branch --merged | egrep -v "(^\*|master|dev)" | xargs -I % echo 'git branch -d % ; git push --delete freephile % ;' | git branch --merged | egrep -v "(^\*|master|dev)" | xargs -I % echo 'git branch -d % ; git push --delete freephile % ;' | ||
</ | </syntaxhighlight> | ||
Using '''echo''' helps you look before you leap. '''%''' is the replacement string in <code>xargs</code>. Change '<code>echo</code>' to '<code>sh -c</code>' to execute. Does both local and remote prunes. | Using '''echo''' helps you look before you leap. '''%''' is the replacement string in <code>xargs</code>. Change '<code>echo</code>' to '<code>sh -c</code>' to execute. Does both local and remote prunes. | ||
| Line 230: | Line 230: | ||
<code>--stat</code> gives a nice view of what happened in the log. | <code>--stat</code> gives a nice view of what happened in the log. | ||
< | <syntaxhighlight lang="bash"> | ||
git log --stat | git log --stat | ||
# try these other git log variatiations | # try these other git log variatiations | ||
| Line 254: | Line 254: | ||
git log --since 'last week' | git log --since 'last week' | ||
git log --since 2017-01-01 | git log --since 2017-01-01 | ||
</ | </syntaxhighlight> | ||
How do you ignore a directory, but make an exception? What if you already added certain directories to git but want to stop tracking them now (ie. "take them out of version control")? | How do you ignore a directory, but make an exception? What if you already added certain directories to git but want to stop tracking them now (ie. "take them out of version control")? | ||
| Line 267: | Line 267: | ||
</pre> | </pre> | ||
Then you simply remove all files from git's index, and add them back (only now adding them back will look to .gitignore for the corrected rules) | Then you simply remove all files from git's index, and add them back (only now adding them back will look to .gitignore for the corrected rules) | ||
< | <syntaxhighlight lang="bash"> | ||
git rm -r --cached . | git rm -r --cached . | ||
git add . | git add . | ||
git commit -m 'ignoring vendor/*' | git commit -m 'ignoring vendor/*' | ||
</ | </syntaxhighlight> | ||
==Tags== | ==Tags== | ||
With git, you can just tag something with <code>git tag foo</code>. This produces a 'lightweight' tag <ref>[https://stackoverflow.com/questions/21031201/how-can-i-list-all-lightweight-tags how can I list all the lightweight tags]</ref>. Use "annotated tags" whenever you want to know '''when''' something was tagged and '''who''' did it. Pass an empty message if you really don't care or need extra annotation. | With git, you can just tag something with <code>git tag foo</code>. This produces a 'lightweight' tag <ref>[https://stackoverflow.com/questions/21031201/how-can-i-list-all-lightweight-tags how can I list all the lightweight tags]</ref>. Use "annotated tags" whenever you want to know '''when''' something was tagged and '''who''' did it. Pass an empty message if you really don't care or need extra annotation. | ||
< | <syntaxhighlight lang="bash"> | ||
git tag -am '' 'REL-1.0-alpha' | git tag -am '' 'REL-1.0-alpha' | ||
</ | </syntaxhighlight> | ||
| Line 284: | Line 284: | ||
When using git between a local repository and a single 'origin' remote, it's a simple process to work locally and push things back up to origin. But, what if you have a separate remote repository... perhaps on GitHub, or a collaborator who has similar sources but not using your origin (so disconnected, and perhaps not even linked ancestrally like a fork). How do you add that other remote to your project and then pull in the code "they" have on top of yours? Here's an example of how we started with a repo from github and added a repo that we were developing privately. (The reality is that we were developing a repo privately; created a sibling version of the code at github; and then wanted to re-incorporate the changes of the github repo back into our private repo.) | When using git between a local repository and a single 'origin' remote, it's a simple process to work locally and push things back up to origin. But, what if you have a separate remote repository... perhaps on GitHub, or a collaborator who has similar sources but not using your origin (so disconnected, and perhaps not even linked ancestrally like a fork). How do you add that other remote to your project and then pull in the code "they" have on top of yours? Here's an example of how we started with a repo from github and added a repo that we were developing privately. (The reality is that we were developing a repo privately; created a sibling version of the code at github; and then wanted to re-incorporate the changes of the github repo back into our private repo.) | ||
< | <syntaxhighlight lang="bash"> | ||
# start with one 'origin' remote | # start with one 'origin' remote | ||
git clone https://github.com/freephile/qb.git | git clone https://github.com/freephile/qb.git | ||
| Line 312: | Line 312: | ||
# and push to other remote 'eqt' | # and push to other remote 'eqt' | ||
git push eqt | git push eqt | ||
</ | </syntaxhighlight> | ||
==Unbloat== | ==Unbloat== | ||
| Line 318: | Line 318: | ||
https://stackoverflow.com/questions/3797907/how-to-remove-unused-objects-from-a-git-repository | https://stackoverflow.com/questions/3797907/how-to-remove-unused-objects-from-a-git-repository | ||
< | <syntaxhighlight lang="bash"> | ||
git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \ | git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \ | ||
-c gc.rerereresolved=0 -c gc.rerereunresolved=0 \ | -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \ | ||
-c gc.pruneExpire=now gc | -c gc.pruneExpire=now gc | ||
</ | </syntaxhighlight> | ||
==Put your project on GitHub== | ==Put your project on GitHub== | ||
| Line 341: | Line 341: | ||
<br /> | <br /> | ||
< | <syntaxhighlight lang="bash"> | ||
# first make a "bare" clone | # first make a "bare" clone | ||
# from your server | # from your server | ||
| Line 362: | Line 362: | ||
git push --set-upstream github master | git push --set-upstream github master | ||
# from now on you can just 'git push' from master | # from now on you can just 'git push' from master | ||
</ | </syntaxhighlight> | ||
==Create a README from a webpage== | ==Create a README from a webpage== | ||
Now create a fine README file using [[pandoc]] to convert your webpage to [[Markdown]] | Now create a fine README file using [[pandoc]] to convert your webpage to [[Markdown]] | ||
< | <syntaxhighlight lang="bash"> | ||
pandoc --standalone --read html https://freephile.org/barcode/index.html -o README.md | pandoc --standalone --read html https://freephile.org/barcode/index.html -o README.md | ||
</ | </syntaxhighlight> | ||
==Remember your password== | ==Remember your password== | ||