Git notes: Difference between revisions
(34 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== Tips and Tricks == | == Tips and Tricks == | ||
=== Bare repos === | |||
when making a new repo that will "receive" stuff use --bare | when making a new repo that will "receive" stuff use --bare | ||
Line 40: | Line 42: | ||
error: failed to push some refs to '/data/gitroot/home' | error: failed to push some refs to '/data/gitroot/home' | ||
</pre> | </pre> | ||
=== Examine a commit before a push === | |||
git diff --cached | |||
== Visualizing changes == | |||
aka browsing changes in a terminal. | |||
use "tig" | |||
[[image:tig-scheen-shot.png|1000px]] | |||
RHEL like: | |||
yum install tig | |||
deb. like: | |||
apt-get install tig | |||
also kdiff3 | |||
on mac like this: | |||
git config --global merge.tool "kdiff3" | |||
in .gitconfig | |||
<pre> | |||
[merge] | |||
conflictstyle = diff3 | |||
tool = kdiff3 | |||
[difftool "kdiff3"] | |||
path = /Applications/kdiff3.app/Contents/MacOS/kdiff3 | |||
</pre> | |||
also: | |||
.gitconfig | |||
<pre> | |||
[alias] | |||
lg = lg1 | |||
lg1 = lg1-specific --all | |||
lg2 = lg2-specific --all | |||
lg3 = lg3-specific --all | |||
lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' | |||
lg2-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' | |||
lg3-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n'' %C(white)%s%C(reset)%n'' %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)' | |||
</pre> | |||
from: https://stackoverflow.com/questions/1838873/visualizing-branch-topology-in-git | |||
== Show log == | |||
git log --name-only | |||
git log --name-status | |||
git log --stat | |||
== Basics == | == Basics == | ||
Line 73: | Line 137: | ||
=== taking all branches from remote and sending them to another === | === taking all branches from remote and sending them to another === | ||
ensure that you have | ensure that you have defined both source and destination remotes in your local repo. | ||
git remote -v | git remote -v | ||
Line 84: | Line 148: | ||
git push destintion refs/remotes/source/*:refs/heads/* | git push destintion refs/remotes/source/*:refs/heads/* | ||
=== detached head? don't lose your head. === | |||
To recover from your situation, you should create a branch that points to the commit currently pointed to by your detached HEAD: | |||
git branch temp | |||
git checkout temp | |||
(these two commands can be abbreviated as git checkout -b temp) | |||
This will reattach your HEAD to the new temp branch. | |||
Next, you should compare the current commit (and its history) with the normal branch on which you expected to be working: | |||
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp | |||
git diff master temp | |||
git diff origin/master temp | |||
(You will probably want to experiment with the log options: add -p, leave off --pretty=… to see the whole log message, etc.) | |||
If your new temp branch looks good, you may want to update (e.g.) master to point to it: | |||
git branch -f master temp | |||
git checkout master | |||
(these two commands can be abbreviated as git checkout -B master temp) | |||
You can then delete the temporary branch: | |||
git branch -d temp | |||
Finally, you will probably want to push the reestablished history: | |||
git push origin master | |||
== Delete a branch here and there == | |||
first locally get out of the branch locally: | |||
git checkout develop | |||
Switched to branch 'develop' | |||
Your branch is up to date with 'origin/develop'. | |||
Now remove the local branch: | |||
git branch -D TICKET-345-Stuff | |||
Deleted branch TICKET-345-Stuff (was c26dbd84). | |||
then push the delete upstream: | |||
git push origin :TICKET-345-Stuff | |||
== Deleting your master branch == | |||
<p>You’ve forked some project on github.</p> | |||
<p>You clone your fork.</p> | |||
<p>Now you’ve got a <code class="docutils literal"><span class="pre">master</span></code> branch. It’s the <code class="docutils literal"><span class="pre">master</span></code> branch of your fork.</p> | |||
<p>It can be tempting to do work in the master branch and ask for a pull request.</p> | |||
<p>That is best avoided because:</p> | |||
<ul class="simple"> | |||
<li>It’s natural to carry on working in your <code class="docutils literal"><span class="pre">master</span></code> and that will pollute your | |||
pull request with other commits</li> | |||
<li><code class="docutils literal"><span class="pre">master</span></code> is not a descriptive name for a set of changes. It’s easier for | |||
the person reviewing your code to have something like <code class="docutils literal"><span class="pre">fix-for-issue-12</span></code>.</li> | |||
<li>You may well also have a tracking branch pointing to the main upstream repo. | |||
You might call that something like <code class="docutils literal"><span class="pre">upstream-master</span></code>. It’s easy to lose | |||
concentration and forget you are on <code class="docutils literal"><span class="pre">upstream-master</span></code> instead of your | |||
<code class="docutils literal"><span class="pre">master</span></code>, and nasty errors can result.</li> | |||
</ul> | |||
<p>To avoid this, I delete the <code class="docutils literal"><span class="pre">master</span></code> branch from my forked copy. However, to | |||
make that work, you have to tell <a class="reference external" href="http://github.com">github</a> not to monitor your <code class="docutils literal"><span class="pre">master</span></code> branch.</p> | |||
<div class="section" id="how-to-delete-master"> | |||
=== How to delete master === | |||
<p>First you delete <code class="docutils literal"><span class="pre">master</span></code> in your local clone. To do this we first make a new | |||
branch called <code class="docutils literal"><span class="pre">placeholder</span></code> or similar, and delete <code class="docutils literal"><span class="pre">master</span></code> from there:</p> | |||
<div class="highlight-python"><div class="highlight"><pre>git branch placeholder | |||
git checkout placeholder | |||
git branch -D master | |||
</pre></div> | |||
</div> | |||
<p>All good so far. We next want to delete the branch on github. However, if we | |||
do this the naive way:</p> | |||
<div class="highlight-python"><div class="highlight"><pre>git push origin :master | |||
</pre></div> | |||
</div> | |||
<p>we just get an error like this:</p> | |||
<div class="highlight-python"><div class="highlight"><pre>remote: error: refusing to delete the current branch: refs/heads/master | |||
To git@github.com:matthew-brett/datarray.git | |||
! [remote rejected] master (deletion of the current branch prohibited) | |||
error: failed to push some refs to 'git@github.com:matthew-brett/datarray.git' | |||
</pre></div> | |||
</div> | |||
<p>That is because github is looking at the <code class="docutils literal"><span class="pre">master</span></code> branch to provide the web | |||
content when you browse that repository. So we first have to make github look | |||
at our <code class="docutils literal"><span class="pre">placeholder</span></code> branch instead, then delete <code class="docutils literal"><span class="pre">master</span></code>.</p> | |||
<p>First push up the <code class="docutils literal"><span class="pre">placeholder</span></code> branch:</p> | |||
<div class="highlight-python"><div class="highlight"><pre>git checkout placeholder # if not on placeholder already | |||
git push origin placeholder | |||
</pre></div> | |||
</div> | |||
<p>Then set <code class="docutils literal"><span class="pre">placeholder</span></code> to be the github default branch. Go to the main github | |||
page for your forked repository, and click on the “Admin” button.</p> | |||
<p>There’s a “Default branch” dropdown list near the top of the screen. From | |||
there, select <code class="docutils literal"><span class="pre">placeholder</span></code>. On the interface I’m looking at, a green tick | |||
appears above the dropdown list. Now you can do (from the command line):</p> | |||
<div class="highlight-python"><div class="highlight"><pre>git push origin :master | |||
</pre></div> | |||
</div> | |||
<p>and - no master branch...</p> | |||
== Do I need to pull? == | |||
In a script you want to know if there have been updates upstream | |||
1. list refs: | |||
git show-ref | |||
2. compare local master with remove master: | |||
$ git rev-parse refs/heads/master | |||
62630806fa6dd6241b4ad3a2e17602a408028948 | |||
$ git rev-parse refs/remotes/origin/master | |||
62630806fa6dd6241b4ad3a2e17602a408028948 | |||
Same, no pull required. | |||
now script that. | |||
== Update submodules == | |||
go to the repo that has the submodule | |||
navigate into the submodule | |||
git checkout master | |||
git pull | |||
navigate outside of the submodule | |||
git status # see stuff | |||
git add submodule-path | |||
git commit -m "I updated a submodule" | |||
== My Develop won't merge into master == | |||
( maybe you should not merge ,you should rebase ) | |||
1. git checkout develop (or w/ever is your SOURCE branch) | |||
2. git pull origin master (or w/ever is your TARGET branch) | |||
3. git merge-tool or git checkout --ours/theirs <files-with-conflicts>, or "code ." "choose use incoming" | |||
4. git commit | |||
5. git push (to your SOURCE branch) | |||
6. attempt MR again | |||
== Rebase might do you better than merge ever did == | |||
https://www.atlassian.com/git/tutorials/merging-vs-rebasing | |||
merge rolls back to when you forked the parent, rolls the parent forward, then applied you changed to the head of the parent. | |||
== cherry picking is fun == | |||
check out the destination branch | |||
git checkout master | |||
create a new branch from that: | |||
git checkout -b TICKET#-Short-descr | |||
cheery pick the commit where you made the messy change: | |||
git cherry-pick b71c4a89b82154c0b239e8af16d54305047ff8ea | |||
git mergetool | |||
see how local working dir has changed: | |||
git status | |||
fix the files / search "===" | |||
vi .gitlab-ci.yml | |||
vi deployment/templates/scheduler/deployment.yaml.j2 | |||
add / commit | |||
git add .gitlab-ci.yml | |||
git add deployment/templates/scheduler/deployment.yaml.j2 | |||
commit with no message: | |||
git commit | |||
editor opens with stuff in it already. | |||
== Git config == | |||
Setting ssh binary: | |||
git config --global core.sshCommand "some/path" | |||
reference: https://git-scm.com/docs/git-config ( all options ) | |||
== Workflow notes == | |||
you branched of dev to get some work done. | |||
but develop has moved on since you did this, how to "catch up"? | |||
git pull origin develop --rebase | |||
== Your branch is ahead of 'origin/master' by X commits == | |||
Some-how you have local master branch commits that put it _ahead_ of upstream. | |||
You want to nuke those commits and get back to the upstream master. | |||
We assume that you don't want those commits. If you want to know what those were do it now before we nuke them from orbit. | |||
Destroy the local branch | |||
$ git checkout develop | |||
Switched to branch 'develop' | |||
$ git branch -D master | |||
Deleted branch master (was 0fd92c3f). | |||
$ git checkout origin/master -b master | |||
Branch 'master' set up to track remote branch 'master' from 'origin'. | |||
Switched to a new branch 'master' | |||
$ git pull | |||
Already up to date. | |||
$ git branch | |||
develop | |||
drttestautobuild | |||
* master | |||
== Get all remote tags == | |||
git fetch --all --tags --prune | |||
== update remote branches == | |||
git remote update origin --prune | |||
== Process: new branch, new tag push == | |||
git checkout master | |||
git pull origin master | |||
# make a new branch | |||
git checkout -b drttestautobuild | |||
git tag -a autobuild1.6.28 -m "my autobuild of v1.6.28" | |||
# push the new tag to a remote: | |||
git push myremote autobuild1.6.28 | |||
== References == | == References == | ||
* https://csswizardry.com/2017/05/little-things-i-like-to-do-with-git/ | |||
* http://mislav.uniqpath.com/2010/07/git-tips/ | * http://mislav.uniqpath.com/2010/07/git-tips/ | ||
* http://longair.net/blog/2009/04/16/git-fetch-and-merge/ | * http://longair.net/blog/2009/04/16/git-fetch-and-merge/ | ||
* Semantic Versioning http://semver.org/ | |||
* Managing git repo size https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html |
Latest revision as of 20:44, 16 February 2023
Tips and Tricks
Bare repos
when making a new repo that will "receive" stuff use --bare
ssh server user@server$ cd /data/gitroot user@server$ git init --bare mynewproject ssh desktop user@desktop$ cd /home/david/work user@desktop$ git init mynewproject user@desktop$ touch myfile && git add myfile && git commit -m "initial import" user@desktop$ git remote add origin ssh://user@server:/data/gitroot/mynewproject user@desktop$ git push -u origin master
If you do not "git init --bare projectname" on the server then you might get something like this:
david@keres ~ $ git push -u origin master Counting objects: 5, done. Delta compression using up to 2 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 1.28 KiB | 0 bytes/s, done. Total 5 (delta 0), reused 0 (delta 0) remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: error: is denied, because it will make the index and work tree inconsistent remote: error: with what you pushed, and will require 'git reset --hard' to match remote: error: the work tree to HEAD. remote: error: remote: error: You can set 'receive.denyCurrentBranch' configuration variable to remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into remote: error: its current branch; however, this is not recommended unless you remote: error: arranged to update its work tree to match what you pushed in some remote: error: other way. remote: error: remote: error: To squelch this message and still keep the default behaviour, set remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'. To /data/gitroot/home ! [remote rejected] master -> master (branch is currently checked out) error: failed to push some refs to '/data/gitroot/home'
Examine a commit before a push
git diff --cached
Visualizing changes
aka browsing changes in a terminal.
use "tig"
RHEL like:
yum install tig
deb. like:
apt-get install tig
also kdiff3
on mac like this:
git config --global merge.tool "kdiff3"
in .gitconfig
[merge] conflictstyle = diff3 tool = kdiff3 [difftool "kdiff3"] path = /Applications/kdiff3.app/Contents/MacOS/kdiff3
also:
.gitconfig
[alias] lg = lg1 lg1 = lg1-specific --all lg2 = lg2-specific --all lg3 = lg3-specific --all lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' lg2-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' lg3-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n'' %C(white)%s%C(reset)%n'' %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)'
from: https://stackoverflow.com/questions/1838873/visualizing-branch-topology-in-git
Show log
git log --name-only
git log --name-status
git log --stat
Basics
get some code:
git clone username@gitserver:/srv/gitroot/ugo-project.git
branches
list branches
git branch
make a new branch
git branch <newbranchname>
switch between branches
git checkout <branchname>
for example to switch back to master:
git checkout master
Maintenance
Backup
Clean up
taking all branches from remote and sending them to another
ensure that you have defined both source and destination remotes in your local repo.
git remote -v source url (fetch) source url (push) destination url (fetch) destination url (push)
then do it like this:
git push destintion refs/remotes/source/*:refs/heads/*
detached head? don't lose your head.
To recover from your situation, you should create a branch that points to the commit currently pointed to by your detached HEAD:
git branch temp git checkout temp
(these two commands can be abbreviated as git checkout -b temp)
This will reattach your HEAD to the new temp branch.
Next, you should compare the current commit (and its history) with the normal branch on which you expected to be working:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp git diff master temp git diff origin/master temp
(You will probably want to experiment with the log options: add -p, leave off --pretty=… to see the whole log message, etc.)
If your new temp branch looks good, you may want to update (e.g.) master to point to it:
git branch -f master temp git checkout master
(these two commands can be abbreviated as git checkout -B master temp)
You can then delete the temporary branch:
git branch -d temp
Finally, you will probably want to push the reestablished history:
git push origin master
Delete a branch here and there
first locally get out of the branch locally:
git checkout develop Switched to branch 'develop' Your branch is up to date with 'origin/develop'.
Now remove the local branch:
git branch -D TICKET-345-Stuff Deleted branch TICKET-345-Stuff (was c26dbd84).
then push the delete upstream:
git push origin :TICKET-345-Stuff
Deleting your master branch
You’ve forked some project on github.
You clone your fork.
Now you’ve got a master
branch. It’s the master
branch of your fork.
It can be tempting to do work in the master branch and ask for a pull request.
That is best avoided because:
- It’s natural to carry on working in your
master
and that will pollute your pull request with other commits master
is not a descriptive name for a set of changes. It’s easier for the person reviewing your code to have something likefix-for-issue-12
.- You may well also have a tracking branch pointing to the main upstream repo.
You might call that something like
upstream-master
. It’s easy to lose concentration and forget you are onupstream-master
instead of yourmaster
, and nasty errors can result.
To avoid this, I delete the master
branch from my forked copy. However, to
make that work, you have to tell <a class="reference external" href="http://github.com">github</a> not to monitor your master
branch.
How to delete master
First you delete master
in your local clone. To do this we first make a new
branch called placeholder
or similar, and delete master
from there:
git branch placeholder
git checkout placeholder
git branch -D master
All good so far. We next want to delete the branch on github. However, if we do this the naive way:
git push origin :master
we just get an error like this:
remote: error: refusing to delete the current branch: refs/heads/master
To git@github.com:matthew-brett/datarray.git
! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to 'git@github.com:matthew-brett/datarray.git'
That is because github is looking at the master
branch to provide the web
content when you browse that repository. So we first have to make github look
at our placeholder
branch instead, then delete master
.
First push up the placeholder
branch:
git checkout placeholder # if not on placeholder already
git push origin placeholder
Then set placeholder
to be the github default branch. Go to the main github
page for your forked repository, and click on the “Admin” button.
There’s a “Default branch” dropdown list near the top of the screen. From
there, select placeholder
. On the interface I’m looking at, a green tick
appears above the dropdown list. Now you can do (from the command line):
git push origin :master
and - no master branch...
Do I need to pull?
In a script you want to know if there have been updates upstream
1. list refs:
git show-ref
2. compare local master with remove master:
$ git rev-parse refs/heads/master 62630806fa6dd6241b4ad3a2e17602a408028948 $ git rev-parse refs/remotes/origin/master 62630806fa6dd6241b4ad3a2e17602a408028948
Same, no pull required.
now script that.
Update submodules
go to the repo that has the submodule
navigate into the submodule
git checkout master git pull
navigate outside of the submodule
git status # see stuff git add submodule-path git commit -m "I updated a submodule"
My Develop won't merge into master
( maybe you should not merge ,you should rebase )
1. git checkout develop (or w/ever is your SOURCE branch) 2. git pull origin master (or w/ever is your TARGET branch) 3. git merge-tool or git checkout --ours/theirs <files-with-conflicts>, or "code ." "choose use incoming" 4. git commit 5. git push (to your SOURCE branch) 6. attempt MR again
Rebase might do you better than merge ever did
https://www.atlassian.com/git/tutorials/merging-vs-rebasing
merge rolls back to when you forked the parent, rolls the parent forward, then applied you changed to the head of the parent.
cherry picking is fun
check out the destination branch
git checkout master
create a new branch from that:
git checkout -b TICKET#-Short-descr
cheery pick the commit where you made the messy change:
git cherry-pick b71c4a89b82154c0b239e8af16d54305047ff8ea git mergetool
see how local working dir has changed:
git status
fix the files / search "==="
vi .gitlab-ci.yml vi deployment/templates/scheduler/deployment.yaml.j2
add / commit
git add .gitlab-ci.yml git add deployment/templates/scheduler/deployment.yaml.j2
commit with no message:
git commit
editor opens with stuff in it already.
Git config
Setting ssh binary:
git config --global core.sshCommand "some/path"
reference: https://git-scm.com/docs/git-config ( all options )
Workflow notes
you branched of dev to get some work done.
but develop has moved on since you did this, how to "catch up"?
git pull origin develop --rebase
Your branch is ahead of 'origin/master' by X commits
Some-how you have local master branch commits that put it _ahead_ of upstream.
You want to nuke those commits and get back to the upstream master.
We assume that you don't want those commits. If you want to know what those were do it now before we nuke them from orbit.
Destroy the local branch
$ git checkout develop Switched to branch 'develop' $ git branch -D master Deleted branch master (was 0fd92c3f). $ git checkout origin/master -b master Branch 'master' set up to track remote branch 'master' from 'origin'. Switched to a new branch 'master' $ git pull Already up to date. $ git branch develop drttestautobuild * master
Get all remote tags
git fetch --all --tags --prune
update remote branches
git remote update origin --prune
Process: new branch, new tag push
git checkout master git pull origin master # make a new branch git checkout -b drttestautobuild git tag -a autobuild1.6.28 -m "my autobuild of v1.6.28" # push the new tag to a remote: git push myremote autobuild1.6.28
References
- https://csswizardry.com/2017/05/little-things-i-like-to-do-with-git/
- http://mislav.uniqpath.com/2010/07/git-tips/
- http://longair.net/blog/2009/04/16/git-fetch-and-merge/
- Semantic Versioning http://semver.org/
- Managing git repo size https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html