Git
TASKS
git new shared central bare repo |
---|
On central server (aka bitpost):
cd development(...) git init --bare --shared mynewthang.git On development box cd development(...) git clone bitpost.com:development/mynewthang.git # this will create a new empty repo with no branch yet # create files, then use git to add them, commit them and push them # that will create remote-tracked master branch for you Back on bitpost git clone mynewthang.git # to create a working copy on server, if desired |
create shared central repo for existing code |
---|
Create a bare repo with .git suffix
git init --bare --shared mything.git Go to existing code and clone the repo next to it, with a temp name. Move .git into the existing code. Add code, add a .gitignore as needed, and you're all set. cd mything/.. git clone (bare-repo-host-and-path)mything.git mything-temp mv mything-temp/.git mything/ rm -rf mything-temp cd mything subl .gitignore # as needed git add (whatever you want to track) git commit -a -m "init repo" && git push |
Set default branch of a bare repo |
---|
If you want the default branch of a bare repo to be something other than master:
git branch * master moodboom-quick-http git symbolic-ref HEAD refs/heads/moodboom-quick-http git branch master * moodboom-quick-http |
gitflow |
---|
Gitflow is awesome, using it myself and everywhere I work these days (2020).
git tag -a -m "#MAJOR#.#MINOR#".0 #MAJOR#.#MINOR#.0 git checkout -b release/release_#MAJOR#.#MINOR# git push --set-upstream origin release_#MAJOR#.#MINOR# git checkout master && git merge release/release_#MAJOR#.#MINOR# && git push git checkout develop # and get back to it!
|
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 |
Push any branch from bare to origin |
---|
Good for when you are force-pushing a branch rebase.
git push [-f] origin mybranch:mybranch |
git merging conflicts after diverging |
---|
Revert local changes in a file to HEAD
git checkout -- path/to/file.txt Discard ALL LOCAL COMMITS and get the (possibly diverged) remote instead git reset --hard origin/master |
git 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).
git checkout -b feature/whiz-bang # Do this ONCE: git config --global push.default current # From then on: git push -u # OR, if you don't want the config, you have to be more specific: # git push -u origin feature/whiz-bang |
getting upstream commits into your GitLab GITFLOW fork |
---|
NOTE: This doesn't work from a bitpost bare repo, so you need to make a new direct clone of your GitLab fork, first, if you don't have one yet.
This is very easy if you have left the master branch alone for the parent's commits, and keep your add-on commits in a release-x.x branch, as we have for SWS and SWSS. cdl # Clone local repo directly from GitLab (already done on cobra) git clone git@gitlab.com:moodboom/Simple-Web-Server.git SWS-gitlab-moodboom cd SWS-gitlab-moodboom # make sure master is checked out git branch # add parent as remote git remote add ole-upstream git@gitlab.com:eidheim/Simple-Web-Server.git git fetch ole-upstream git rebase ole-upstream/master git push -f origin master You can now delete the fresh clone, it has done its job. Or leave it for ease-of-use for next rebase. Now update your bare repo on bitpost, to keep things in sync. git fetch origin master:master -f Next, go to dev repo, pull master. Check out release, create a new release from that, and rebase master. (or just create a new release branch off master if that's what you want) It is the gitflow way! Push your new branch to bare, then push bare to GitLab via something like: git push --set-upstream origin release/abt-0.0.3 To complete SW(S)S rebase, update mh-install-sws to use the new branch. Then run it on all your dev boxes, whoop. (Then, code up any fixes, sigh... and push em.. .sigh... and get on with it!) |
getting upstream commits into your GitLab fork |
---|
NOTE: This doesn't work from a bitpost bare repo, so you need to make a new direct clone of your GitLab fork, first, if you don't have one yet.
Add the remote, call it something specific: git remote add someauthor-upstream https://gitlab.com/someauthor/theprojectiforked Fetch all the branches of that remote into remote-tracking branches, such as upstream/master: git fetch someauthor-upstream Get on the branch where you are tracking the rebase. Typically your master branch but can be whatever: git checkout tlsv12 # or master or next or... Rewrite your branch so that any commits of yours that aren't already in upstream are replayed on top of that other branch (if you do a straight merge instead of rebase you'll screw up the upstream!): git rebase someauthor-upstream/master If you haven't done so, in GitLab, go to the "Protected Branch" settings and remove protection from master - it's just a fact that you're going to need to force-push to master. IF the branch that was the target of the rebase existed, force the push in order to push it to your own forked repository on GitLab. You only need to use the -f the first time after you've rebased: git push -f origin master ELSE if the branch you merged into is a new creation, set its upstream when you push: git push --set-upstream origin tlsv12 You will want to force-fetch to update the bare repo you may have on bitpost, DO THIS NOW or you will screw things up badly later: [Simple-WebSocket-Server.git] git fetch origin master:master -f You should also force-update ALL your dev repos, NOW, for the same reason: git reset --hard HEAD^^^^^^ && git pull NOTE that you may need to remove a remote-tracking branch if you don't need it any more. It's stupidly painful to get right, eg: [Simple-WebSocket-Server.git] git branch -rd eidheim/Simple-WebSocket-Server/master |
getting upstream commits into your GitHub fork |
---|
From so...
Add the remote, call it something specific: git remote add someauthor-upstream https://github.com/someauthor/theprojectiforked.git Fetch all the branches of that remote into remote-tracking branches, such as upstream/master: git fetch someauthor-upstream Get on the branch where you are tracking the rebase. Typically your master branch but can be whatever: git checkout tlsv12 # or master or next or... Rewrite your branch so that any commits of yours that aren't already in upstream are replayed on top of that other branch (if you do a straight merge instead of rebase you'll screw up the upstream!): git rebase someauthor-upstream/master IF the branch that was the target of the rebase existed, force the push in order to push it to your own forked repository on GitHub. You only need to use the -f the first time after you've rebased: git push -f origin master ELSE if the branch you merged into is a new creation, set its upstream when you push: git push --set-upstream origin tlsv12 Now master has the latest commits from the fork origin. You can rebase onto it, if you've been working in a branch (good): git checkout mybranch git rebase master |
Clone a bare repo (eg github, gitlab, bb) into a bare repo |
---|
Say you want a bare repo to be shared by all your dev environments, but you need to push/pull THAT from a central bare repo, too.
git clone --bare --shared git@bitbucket.org:equityshift/es-demo.git cd es-demo.git git config remote.origin.fetch "+*:*" git fetch --all I was surprised that this was difficult at all, and may still have some lessons to learn... |
git create new branch on server, pull to client |
---|
# ON CENTRAL SERVER git checkout master # as needed; we are assuming that master is clean enough as a starting point git checkout -b mynewbranchy # HOWEVER, use this instead if you need a new "clean" repo and even master is dirty... # You need the rm because git "leaves your working folder intact". git checkout --orphan mynewbranchy git rm -rf . # ON CLIENT git pull git checkout -b mynewbranchy origin/mynewbranchy # if files are in the way from the previously checked-out branch, you can force it... git checkout -f -b mynewbranchy origin/mynewbranchy |
git merge changes in a single file |
---|
Explanation is here.
git checkout mybranch git checkout --patch develop my/single/file.cpp |
git remove old branches |
---|
Explanation is here.
Remote: git push origin --delete <branch> Local: git branch -d <branch> git fetch <remote> --prune # Delete multiple obsolete tracking branches |
Work with two local repos |
---|
Set up a remote, then fetch it as master.
cd repoToChange git remote add otherplace ../../wherever/../gitrepo git ls-remote otherplace # verify it looks ok, figure out which branch you like (if not master) git fetch otherplace # gets it all git checkout --track otherplace/master # or other branch as needed; this creates the branch and sets remote in one step, cool Set up a remote, then fetch it into a non-master branch, and push it to the active origin. cd repoToChange git remote add otherplace ../../wherever/../gitrepo git ls-remote otherplace # verify it looks ok, figure out which branch you like (if not master) git fetch otherplace # gets it all git checkout otherplace/master # creates it detached, good because we need to name the new branch something other than master git checkout -b new_otherplace_branchname # creates new local branch with a good name git push --set-upstream origin new_otherplace_branchname # takes the branch from the OLD origin and pushes it to the ACTIVE origin, cool! |
git pull when untracked files are in the way |
---|
This will pull, forcing untracked files to be overwritten by newly tracked ones in the repo:
git fetch --all git reset --hard origin/mymatchingbranch |
git create new branch when untracked files are in the way |
---|
git checkout -b bj143 origin/bj143 git : error: The following untracked working tree files would be overwritten by checkout: (etc) TOTAL PURGE FIX (too much): git clean -d -fn "" -d dirs too -f force, required -x include ignored files (don't use this) -n dry run BEST FIX (just overwrite what is in the way): git checkout -f -b bj143 origin/bj143 |
git recreate repo |
---|
git clone ssh://m@thedigitalmachine.com/home/m/development/thedigitalage/ampache-with-hangthedj-module cd ampache-with-hangthedj-module git checkout -b daily_grind origin/daily_grind If you already have the daily_grind branches and just need to connect them: git branch -u origin/daily_grind daily_grind |
git connect to origin after the fact |
---|
git remote add origin ssh:// m@bitpost.com/home/m/development/logs git fetch From ssh:// bitpost/home/m/development/logs * [new branch] daily_grind -> origin/daily_grind * [new branch] master -> origin/master git branch -u origin/daily_grind daily_grind git checkout master git branch -u origin/master master |
git 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 my SO answer.
PREVENT COMMIT OF CHANGES TO A LOCAL FILE ----------------------------------------- git update-index --skip-worktree apps/views/_partials/jsIncludes.scala.html RESET TO GET CHANGES AGAIN -------------------------- git update-index --no-skip-worktree apps/views/_partials/jsIncludes.scala.html LIST SKIPPED FILES ------------------ git ls-files -v . | grep ^S S app/views/_partials/jsIncludes.scala.html ----------------------------------------- |
git changing branches in a project with submodules |
---|
# always reset the @*$ submodules to proper commits git checkout develop && git submodule update |
git hard-reset a misbehaving submodule to parent commit version |
---|
git submodule deinit -f . git submodule update --init |
CONFIGURATION
git visual difftool and mergetool setup |
---|
Meld is purdy, let's kick its tires. Hope it actually works...
git config --global diff.tool meld git config --global merge.tool meld git config --global --add difftool.prompt false I used to set up kdiff3 manually, like this... (gross)
[diff] tool = kdiff3 [merge] tool = kdiff3
[difftool "kdiff3"] path = C:/Progra~1/KDiff3/kdiff3.exe trustExitCode = false [difftool] prompt = false [diff] tool = kdiff3 [mergetool "kdiff3"] path = C:/Progra~1/KDiff3/kdiff3.exe trustExitCode = false [mergetool] keepBackup = false [merge] tool = kdiff3
[difftool "kdiff3"] path = /usr/bin/kdiff3 trustExitCode = false [difftool] prompt = false [diff] tool = kdiff3 [mergetool "kdiff3"] path = /usr/bin/kdiff3 trustExitCode = false [mergetool] keepBackup = false [merge] tool = kdiff3 |
git 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:
cd repo Now you can copy-paste this... mv .git .. && rm -fr * mv ../.git . mv .git/* . rmdir .git git config --bool core.bare true cd .. Don't copy/paste these, you need to change repo name... mv repo repo.git # rename it for clarity git clone repo.git # (optional, if you want a live repo on the server where you have the bare repo) Then you can clean up old branches like daily and daily_grind, as needed. |
git 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.
If you did NOT specify --mirror when you first created the bare repo, you can convert to a mirror by adding these last two lines to config, underneath url: [remote "origin"] url = git@github.com:facebook/proxygen.git fetch = +refs/*:refs/* mirror = true Now you can fetch from the bare repo: git fetch |
git create merge-to command |
---|
Add this handy alias command to all git repos' .config file...
[alias] merge-to = "!gitmergeto() { export tmp_branch=`git branch | grep '* ' | tr -d '* '` && git checkout $1 && git merge $tmp_branch && git checkout $tmp_branch; unset tmp_branch; }; gitmergeto" |
git 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.
Fixing it is a PAIN in the ASS, you have to create a new local repo and pull github into that, pull in from your other local repo, push to github, pull to your bare... git clone git@github.com:moodboom/quick-http.git quick-http-with-readme-conflict git remote add local ../quick-http git fetch local git merge local/master # merge in changes, likely trivial git push # pushes back to github cd .. mv quick-http.git quick-http.git__gone-out-of-sync-fu-github-readme-editor git clone git@github.com:moodboom/quick-http.git --bare cp quick-http.git__gone-out-of-sync-fu-github-readme-editor/config quick-http.git/ And that MIGHT get you on your way... but I would no longer trust ANY of your local repos... This is a serious pita. |
git windows configure notepad++ editor |
---|
git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" |
git fix push behavior - ONLY PUSH CURRENT doh |
---|
git config --global push.default current |
git multiple upstreams |
---|
Use this to cause AUTOMATIC push/pull to a second origin:
git remote set-url origin --push --add user1@repo1 git remote set-url origin --push --add user2@repo2 git remote -v show 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
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...
My git pages (older)
Track your changes to an open-source project with git Using git on Windows Portable git