Git: Difference between revisions
No edit summary |
No edit summary |
||
(25 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=== TASKS === | === TASKS === | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! New shared central bare repo | ||
|- | |- | ||
| On central server (aka | | On central server (aka morosoph): | ||
cd development(...) | cd development(...) | ||
git init --bare --shared mynewthang.git | git init --bare --shared mynewthang.git | ||
On development box | On development box | ||
cd development(...) | cd development(...) | ||
git clone | git clone morosoph:development/mynewthang.git | ||
# this will create a new empty repo with no branch yet | # this will create a new empty repo with no branch yet | ||
# create files, | # TO CREATE MASTER BRANCH (this is the only way): | ||
# create files, git add, git commit, git push | |||
Back on bitpost | Back on bitpost | ||
git clone mynewthang.git # to create a working copy on server, if desired | git clone mynewthang.git # to create a working copy on server, if desired | ||
Line 28: | Line 28: | ||
rm -rf mything-temp | rm -rf mything-temp | ||
cd mything | cd mything | ||
code .gitignore # as needed | |||
git add (whatever you want to track) | git add (whatever you want to track) | ||
git commit -a -m "init repo" && git push | git commit -a -m "init repo" && git push | ||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Fetch a branch from remote without checking it out | |||
|- | |||
| Good for when you are rebasing a feature branch. | |||
git fetch origin develop:develop | |||
You would think <code>git fetch --all</code> would do it but does not (it fetches the active branch from ''all origins'' - seriously wtf, who ever wants THAT??). | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Completely reset an out-of-sync branch to 100% match the remote | |||
|- | |||
| Sometimes some other idiot rebased the remote branch on you. Make sure you are on the right branch, locally. Then to completely force-reset it: | |||
git reset --hard origin/thebranchname | |||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
Line 43: | Line 56: | ||
master | master | ||
* moodboom-quick-http | * moodboom-quick-http | ||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Find a file across branches | |||
|- | |||
| It's clunky, two steps, and you have to glob out the whole fucking name: | |||
# get the commits that involved the filename | |||
git log --all -- '**/*namebits*' | |||
# even better, get the filenames too, and see if it was added or removed: | |||
git log --all --stat -- '**/*namebits*' | |||
# now find the branch with one of those commits: | |||
git branch -a --contains #commithash# | |||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
Line 59: | Line 83: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Interactive rebase with squash | ||
|- | |- | ||
| | | Excellent to do when on your own feature branch. Illegal to do if branch is shared AT ALL! | ||
git | git rebase -i myparentbranch | ||
# work through squash and merge - gitlens may help with squash if you use vscode for EDITOR | |||
git push -f | |||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
Line 72: | Line 97: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! git | ! Fetch from one origin (eg gitlab) and push to another | ||
|- | |||
| My GitLab is usually a mirror, and therefore a push target. But if you edit a file in GitLab, you may need to pull it from remote "gitlab" and push it to remote "sc", like this: | |||
git fetch gitlab develop:develop | |||
git push sc | |||
This assumes you have something like the following in your config: | |||
[remote "sc"] | |||
url = git@shitcutter.com:the-digital-age/rad-scripts.git | |||
fetch = +refs/heads/*:refs/remotes/origin/* | |||
[remote "github.com"] | |||
url = git@github.com:moodboom/rad-scripts.git | |||
fetch = +refs/heads/*:refs/remotes/origin/* | |||
[remote "gitlab.com"] | |||
url = git@gitlab.com:moodboom/rad-scripts.git | |||
fetch = +refs/heads/*:refs/remotes/origin/* | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Merging conflicts after diverging | |||
|- | |- | ||
| Revert local changes in a file to HEAD | | Revert local changes in a file to HEAD | ||
Line 80: | Line 122: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Create and push a feature branch | ||
|- | |- | ||
| This will move recent commits AND uncommitted changes into a new branch (but you probably want to finish by cleaning out commits from starting branch, and repulling after you merge the feature). | | This will move recent commits AND uncommitted changes into a new branch (but you probably want to finish by cleaning out commits from starting branch, and repulling after you merge the feature). | ||
Line 178: | Line 220: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Create new branch on server, pull to client | ||
|- | |- | ||
| | | | ||
Line 197: | Line 239: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Merge changes in a single file | ||
|- | |- | ||
| Explanation is [https://stackoverflow.com/a/11593308/717274 here]. | | Explanation is [https://stackoverflow.com/a/11593308/717274 here]. | ||
Line 204: | Line 246: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Remove old branches | ||
|- | |- | ||
| Explanation is [https://stackoverflow.com/a/23961231/717274 here]. | | Explanation is [https://stackoverflow.com/a/23961231/717274 here]. | ||
Line 232: | Line 274: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Pull when untracked files are in the way | ||
|- | |- | ||
| This will pull, forcing untracked files to be overwritten by newly tracked ones in the repo: | | This will pull, forcing untracked files to be overwritten by newly tracked ones in the repo: | ||
Line 239: | Line 281: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Create new branch when untracked files are in the way | ||
|- | |- | ||
| | | | ||
Line 257: | Line 299: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Recreate repo | ||
|- | |- | ||
| | | | ||
Line 268: | Line 310: | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Connect to origin after the fact | ||
|- | |- | ||
| | | | ||
Line 282: | Line 324: | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Ignore local and remote changes to a file | ||
|- | |- | ||
| This is helpful for conf files that need local-specific modifications that shouldn't be pushed. You have to toggle it on/off as needed to get updates! See [http://stackoverflow.com/questions/4348590/how-can-i-make-git-ignore-future-revisions-to-a-file/39776107#39776107 my SO answer]. | | This is helpful for conf files that need local-specific modifications that shouldn't be pushed. You have to toggle it on/off as needed to get updates! See [http://stackoverflow.com/questions/4348590/how-can-i-make-git-ignore-future-revisions-to-a-file/39776107#39776107 my SO answer]. | ||
Line 301: | Line 343: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! git | ! Replace name and email of last commit | ||
|- | |||
| Reset the name and email of the last commit, when you realize you forgot to set them first: | |||
git commit --amend --author="First Last <email>" --no-edit | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Simple tagging (when not using git-sync) | |||
|- | |||
| To add and push a tag to HEAD: | |||
git tag -a 1.2.0 -m "1.2.0" | |||
git push origin 1.2.0 | |||
To add and push a tag attached to a commit with current time as timestamp: | |||
git tag -a 1.2.0 1bc92e2f -m "1.2.0" | |||
git push origin 1.2.0 | |||
To tag a commit while ensuring the timestamp matches is slightly more complicated (but not bad). More details [https://stackoverflow.com/a/21759466/717274 here]: | |||
# Set the HEAD to the old commit that we want to tag | |||
git checkout 9fceb02 | |||
# temporarily set the date to the date of the HEAD commit, and add the tag | |||
GIT_COMMITTER_DATE="$(git show --format=%aD | head -1)" \ | |||
git tag -a v1.2 -m"v1.2" | |||
# push to origin | |||
git push origin --tags | |||
# set HEAD back to whatever you want it to be | |||
git checkout master | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Remove a tag | |||
|- | |||
| This has a long clumsy history, but these instructions should be good into the future. | |||
To remove remote tag(s): | |||
git push --delete origin tag YOUR_TAG_NAME TAG_NAME_2 ... | |||
Remove tag(s) locally: | |||
git tag -d YOUR_TAG_NAME TAG_NAME_2 ... | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Changing branches in a project with submodules | |||
|- | |- | ||
| | | | ||
Line 308: | Line 391: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Hard-reset a misbehaving submodule to parent commit version | ||
|- | |- | ||
| | | | ||
Line 317: | Line 400: | ||
=== CONFIGURATION === | === CONFIGURATION === | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! git | ! Set name and email | ||
|- | |||
| Globally on one machine (note the machine name at end of user name): | |||
git config --global user.email m@thedigitalmachine.com; git config user.name "Michael Behrns-Miller [cast]" | |||
Override for a repository: | |||
git config user.email mbm@equityshift.io; git config user.name "MBM [cast]" | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Set default root to main not master | |||
|- | |||
| I love the idea of a kinder root name, suck it up alt-right down-punchers, lol. | |||
Configure it to always happen: | |||
git config --global init.defaultBranch main | |||
Fix it for a newly initialized repository: | |||
git branch -m main | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Visual difftool and mergetool setup | |||
|- | |- | ||
| Meld is purdy, let's kick its tires. Hope it actually works... | | Meld is purdy, let's kick its tires. Hope it actually works... | ||
Line 362: | Line 462: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Convert to a bare repo | ||
|- | |- | ||
| Start with a normal git repo via [git init]; add your files, get it all set up. Then do this: | | Start with a normal git repo via [git init]; add your files, get it all set up. Then do this: | ||
Line 379: | Line 479: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Convert bare to a mirror of remote (github, facebook, etc) | ||
|- | |- | ||
| You need a bare mirror repo if you want to take someone else's repo and create your own bare to work from. | | You need a bare mirror repo if you want to take someone else's repo and create your own bare to work from. | ||
Line 391: | Line 491: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Create merge-to command | ||
|- | |- | ||
| Add this handy alias command to all git repos' .config file... | | Add this handy alias command to all git repos' .config file... | ||
Line 399: | Line 499: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Fix github diverge from local bare repo following README.md edit | ||
|- | |- | ||
| Yes editing the README.md file on github will FUCK UP your downstream bare repo if you meanwhile push to it before pulling. | | Yes editing the README.md file on github will FUCK UP your downstream bare repo if you meanwhile push to it before pulling. | ||
Line 416: | Line 516: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Windows configure notepad++ editor | ||
|- | |- | ||
| | | | ||
Line 422: | Line 522: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Fix push behavior - ONLY PUSH CURRENT doh | ||
|- | |- | ||
| | | | ||
Line 428: | Line 528: | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! Multiple upstreams | ||
|- | |- | ||
| Use this to cause AUTOMATIC push/pull to a second origin: | | Use this to cause AUTOMATIC push/pull to a second origin: | ||
Line 436: | Line 536: | ||
Leave out --push if you want to pull as well... but I'd be careful, it's better if code is changed in one client with this config, and then pushed to the multiple origins from there. Otherwise, things are GOING TO GET SYNCY-STINKY. | Leave out --push if you want to pull as well... but I'd be careful, it's better if code is changed in one client with this config, and then pushed to the multiple origins from there. Otherwise, things are GOING TO GET SYNCY-STINKY. | ||
|} | |} | ||
=== Git branching strategies === | === Git branching strategies === | ||
Line 454: | Line 553: | ||
I was a die-hard believer in gitflow for a while. It's very capable. Too capable. You MIGHT need it if you are supporting multiple versions in production... but in all my cases, it is overkill, compared to Simplified Gitflow. The classic diagram, originally from [http://nvie.com/posts/a-successful-git-branching-model/ here]... | I was a die-hard believer in gitflow for a while. It's very capable. Too capable. You MIGHT need it if you are supporting multiple versions in production... but in all my cases, it is overkill, compared to Simplified Gitflow. The classic diagram, originally from [http://nvie.com/posts/a-successful-git-branching-model/ here]... | ||
[[File:Git for nice release planning.png]] | [[File:Git for nice release planning.png]] | ||
=== LFS === | |||
Just don't use it. It's shite. If you get stuck working with a repo that requires it, and you are using ssh on linux which just won't work with LFS... you will probably end up with a damaged repo. Fix it with this: | |||
git read-tree HEAD && GIT_LFS_SKIP_SMUDGE=1 git checkout -f HEAD | |||
After that, use '''GIT_LFS_SKIP_SMUDGE=1''' during any git command: | |||
GIT_LFS_SKIP_SMUDGE=1 git pull # etc. | |||
=== My git pages (older) === | === My git pages (older) === | ||
[[Track your changes to an open-source project with git]] | [[Track your changes to an open-source project with git]] | ||
[[Using git on Windows]] | [[Using git on Windows]] | ||
[[Portable git]] | [[Portable git]] |
Latest revision as of 16:15, 30 November 2024
TASKS
ExpandNew shared central bare repo |
---|
Expandcreate shared central repo for existing code |
---|
ExpandFetch a branch from remote without checking it out |
---|
ExpandCompletely reset an out-of-sync branch to 100% match the remote |
---|
ExpandSet default branch of a bare repo |
---|
ExpandFind a file across branches |
---|
Expandgitflow |
---|
ExpandInteractive rebase with squash |
---|
ExpandPush any branch from bare to origin |
---|
ExpandFetch from one origin (eg gitlab) and push to another |
---|
ExpandMerging conflicts after diverging |
---|
ExpandCreate and push a feature branch |
---|
Expandgetting upstream commits into your GitLab GITFLOW fork |
---|
Expandgetting upstream commits into your GitLab fork |
---|
Expandgetting upstream commits into your GitHub fork |
---|
ExpandClone a bare repo (eg github, gitlab, bb) into a bare repo |
---|
ExpandCreate new branch on server, pull to client |
---|
ExpandMerge changes in a single file |
---|
ExpandRemove old branches |
---|
ExpandWork with two local repos |
---|
ExpandPull when untracked files are in the way |
---|
ExpandCreate new branch when untracked files are in the way |
---|
ExpandRecreate repo |
---|
ExpandConnect to origin after the fact |
---|
ExpandIgnore local and remote changes to a file |
---|
ExpandReplace name and email of last commit |
---|
ExpandSimple tagging (when not using git-sync) |
---|
ExpandRemove a tag |
---|
ExpandChanging branches in a project with submodules |
---|
ExpandHard-reset a misbehaving submodule to parent commit version |
---|
CONFIGURATION
ExpandSet name and email |
---|
ExpandSet default root to main not master |
---|
ExpandVisual difftool and mergetool setup |
---|
ExpandConvert to a bare repo |
---|
ExpandConvert bare to a mirror of remote (github, facebook, etc) |
---|
ExpandCreate merge-to command |
---|
ExpandFix github diverge from local bare repo following README.md edit |
---|
ExpandWindows configure notepad++ editor |
---|
ExpandFix push behavior - ONLY PUSH CURRENT doh |
---|
ExpandMultiple upstreams |
---|
Git branching strategies
Simplified Gitflow
This is awesome, tight, and well-capable of handling any app with a single primary release (like a website).
RELEASE TAG o----------------------------o-----------------o------------o------> MASTER \ / \ \----------/ HOTFIX \ / \ \ \----------------------/ \--------------------o-----o------> DEVELOP \ / \----------------/ FEATURE
Gitflow
I was a die-hard believer in gitflow for a while. It's very capable. Too capable. You MIGHT need it if you are supporting multiple versions in production... but in all my cases, it is overkill, compared to Simplified Gitflow. The classic diagram, originally from here...
LFS
Just don't use it. It's shite. If you get stuck working with a repo that requires it, and you are using ssh on linux which just won't work with LFS... you will probably end up with a damaged repo. Fix it with this:
git read-tree HEAD && GIT_LFS_SKIP_SMUDGE=1 git checkout -f HEAD
After that, use GIT_LFS_SKIP_SMUDGE=1 during any git command:
GIT_LFS_SKIP_SMUDGE=1 git pull # etc.