Difference between revisions of "Short Notes on git"
(→Typical Flow) |
|||
(13 intermediate revisions by one user not shown) | |||
Line 11: | Line 11: | ||
$ git clone user@host:/path/to/repo # create working copy of remote repo | $ git clone user@host:/path/to/repo # create working copy of remote repo | ||
+ | $ git status # get info about local copy, incl. branch ID, changes, etc. | ||
+ | |||
+ | $ git fetch # download changes but do not integrate in the HEAD | ||
$ git pull # update the local copy to the latest revision | $ git pull # update the local copy to the latest revision | ||
+ | $ git pull <remote> <branch> # pull specific branch | ||
$ git diff <source> <dest> # view differences between "source" and "dest" branches | $ git diff <source> <dest> # view differences between "source" and "dest" branches | ||
− | $ git merge <branch> # merge changes from another branch (e.g. "master") | + | $ git merge <branch> # merge changes from another branch (e.g. "origin/master") |
+ | # you should merge from remote ("origin") as your local copy may differ | ||
# set meld as diff and merge tool; use --global to apply globally, not just per-repo | # set meld as diff and merge tool; use --global to apply globally, not just per-repo | ||
Line 27: | Line 32: | ||
$ git commit -m 'message' # commit changes from index to head | $ git commit -m 'message' # commit changes from index to head | ||
$ git push origin master # push changes from head to master branch, or | $ git push origin master # push changes from head to master branch, or | ||
− | $ git push | + | $ git push <remote> <branch> # push changes to <branch> |
$ git checkout -- <file> # revert file and replace with current HEAD version, exc. of changes added to Index | $ git checkout -- <file> # revert file and replace with current HEAD version, exc. of changes added to Index | ||
Line 34: | Line 39: | ||
# branching | # branching | ||
− | $ git checkout -b < | + | $ git branch -av # list existing branches |
− | $ git push origin < | + | $ git checkout -b <branch> # create a new branch, and switch to it, or |
+ | $ git checkout <branch> # switch to branch (make it your HEAD) | ||
+ | $ git push origin <branch> --set-upstream # make the branch available to others, and set the upstream | ||
+ | $ git branch -d <branch> # delete local branch | ||
+ | $ git branch -dr <remote/branch> # delete remote branch | ||
# other stuff | # other stuff | ||
Line 42: | Line 51: | ||
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ... | $ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ... | ||
$ git log --name-status # list changed files | $ git log --name-status # list changed files | ||
+ | |||
+ | # "svn:externals" like inclusion of another repo; need to commit this as well | ||
+ | $ git submodule add -b <branch> <repo> [<folder>] | ||
+ | $ git add <folder> .gitmodules ; + commit ; + push | ||
+ | |||
+ | $ git submodule update --remote # update the submodules from their respective repo's | ||
</pre> | </pre> | ||
== Typical Flow == | == Typical Flow == | ||
− | <pre>$ git clone [remote repo] # get a local copy of the repo | + | <pre> |
+ | $ git clone [remote repo] # get a local copy of the repo | ||
$ git checkout -b <branch> # start a new branch | $ git checkout -b <branch> # start a new branch | ||
+ | $ git push --set-upstream origin <branch> # set remote as upstream, to be able to push to remote repo | ||
# do your changes... | # do your changes... | ||
Line 60: | Line 77: | ||
$ git checkout master # switch to master | $ git checkout master # switch to master | ||
$ git merge <branch> # this should pass ok; commit to "master" afterwards | $ git merge <branch> # this should pass ok; commit to "master" afterwards | ||
− | $ git branch -d <branch> # clean up - remove the branch | + | $ git branch -d <branch> # clean up - remove the branch |
$ git tag <tag> <commit id> # optionally, also tag the commit after merging | $ git tag <tag> <commit id> # optionally, also tag the commit after merging | ||
+ | </pre> | ||
+ | |||
+ | === Resolve Conflict === | ||
+ | |||
+ | If on <tt>git pull</tt> you get a message: | ||
+ | <pre>error: Your local changes to the following files would be overwritten by merge: | ||
+ | [list of files] | ||
+ | Please, commit your changes or stash them before you can merge. | ||
+ | Aborting</pre> | ||
+ | |||
+ | You need to resolve the conflict manually. | ||
+ | |||
+ | <pre>git fetch | ||
+ | git add [file] | ||
+ | git commit -m 'resolving' | ||
+ | git merge</pre> | ||
+ | |||
+ | At which point you'll get message: | ||
+ | |||
+ | <pre>Auto-merging [files] | ||
+ | CONFLICT (content): Merge conflict in [files] | ||
+ | Automatic merge failed; fix conflicts and then commit the result.</pre> | ||
+ | |||
+ | Now you need to manually edit the file(s) to resolve the conflict, and then <tt>add/commit</tt> the resolved file(s). | ||
+ | |||
+ | == Small Tips == | ||
+ | |||
+ | === Skip Retyping Your Password === | ||
+ | |||
+ | <pre>$ git config --global credential.helper store</pre> | ||
+ | |||
+ | Run <tt>git pull</tt> and enter your username and password. These will be stored in <tt>~/.git-credentials</tt> file and reused each time. | ||
+ | |||
+ | === Ignoring Files and Folders === | ||
+ | |||
+ | <pre>$ touch .gitignore | ||
+ | # edit the file with your fave editor (folders should end with '/'): | ||
+ | folder/ | ||
+ | file.txt | ||
+ | |||
+ | # it's good practice to commit the file as well | ||
+ | $ git add .gitignore | ||
+ | $ git commit -m "Added .gitignore file" | ||
+ | $ git push origin master</pre> | ||
+ | |||
+ | === Current Branch === | ||
+ | |||
+ | <pre>git rev-parse --abbrev-ref HEAD</pre> | ||
+ | |||
+ | You can add this to <tt>.git/config</tt> as alias: | ||
+ | |||
+ | <pre>[alias] | ||
+ | current = rev-parse --abbrev-ref HEAD</pre> | ||
+ | |||
+ | and then use it as | ||
+ | |||
+ | <pre>$ git current | ||
+ | > master</pre> | ||
+ | |||
+ | === Set ''meld'' as your <tt>difftool</tt> and <tt>mergetool</tt> === | ||
+ | |||
+ | Edit your <tt>~/.gitconfig</tt> file as follows: | ||
+ | |||
+ | <pre>[diff] | ||
+ | tool = meld | ||
+ | [difftool] | ||
+ | prompt = false | ||
+ | [difftool "meld"] | ||
+ | cmd = meld "$LOCAL" "$REMOTE"</pre> | ||
+ | |||
+ | Now, running <tt>git difftool</tt> will bring up your dear ol' ''meld''. | ||
+ | |||
+ | For resolution of merge conflicts, add to your <tt>~/.gitconfig</tt> file, choosing one of the two options: | ||
+ | |||
+ | <pre>[merge] | ||
+ | tool = meld | ||
+ | [mergetool "meld"] | ||
+ | # the middle file is the partially merged file, and you have to | ||
+ | # make sense of the conflicting portions | ||
+ | cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED" | ||
+ | # the middle file is the "common ancestor" of the conflicting files, | ||
+ | # and you have to choose bits and pieces to reconstruct the new merged file | ||
+ | cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"</pre> | ||
− | + | First option turns out better in case there was lots to merge, and just bit to resolve. | |
− | + | The second option is better when pretty much all changes are in conflict, and reconstructing things by hand turns out easier. | |
− | + | ||
− | + | ||
− | + |
Latest revision as of 02:58, 20 March 2021
Contents
Basic Commands
The git has 3 "trees" maintained automatically within your local repo - "working copy" is the files you're actually working on, "index" is kind of staging area, and "head" is your last actual commit. You're working on your working copy, then add changes to the index, then push those to head locally, and finally push those to (remote) repo.
# two ways to check out a repo; 1) first local, then connect $ git init # init local copy $ git remote add origin <server> # connect it to remote # or, 2) checkout a remote repo straight away $ git clone /path/to/repo # create working copy of local repo $ git clone user@host:/path/to/repo # create working copy of remote repo $ git status # get info about local copy, incl. branch ID, changes, etc. $ git fetch # download changes but do not integrate in the HEAD $ git pull # update the local copy to the latest revision $ git pull <remote> <branch> # pull specific branch $ git diff <source> <dest> # view differences between "source" and "dest" branches $ git merge <branch> # merge changes from another branch (e.g. "origin/master") # you should merge from remote ("origin") as your local copy may differ # set meld as diff and merge tool; use --global to apply globally, not just per-repo $ git config difftool meld $ git config difftool.prompt false # don't ask each time whether to run meld $ git config mergetool meld # don't ask each time whether to run meld $ git config mergetool.prompt false $ git difftool # you need to use "difftool" to run meld for diff, not just `git diff` $ git mergetool # run this only after `git merge` if there are any conflicts to be resolved # getting the changes to the remote repo $ git add [-i] <file> # add changes from file(s) to index (-i = interactive) $ git commit -m 'message' # commit changes from index to head $ git push origin master # push changes from head to master branch, or $ git push <remote> <branch> # push changes to <branch> $ git checkout -- <file> # revert file and replace with current HEAD version, exc. of changes added to Index $ git fetch origin # fetch latest history from server $ git reset --hard origin/master # drop all local changes, incl. those in Index # branching $ git branch -av # list existing branches $ git checkout -b <branch> # create a new branch, and switch to it, or $ git checkout <branch> # switch to branch (make it your HEAD) $ git push origin <branch> --set-upstream # make the branch available to others, and set the upstream $ git branch -d <branch> # delete local branch $ git branch -dr <remote/branch> # delete remote branch # other stuff $ git tag <tag name> <commit id> # create tag from a commit $ git log --pretty=oneline [--author=<name>] # one-line per commit listing $ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ... $ git log --name-status # list changed files # "svn:externals" like inclusion of another repo; need to commit this as well $ git submodule add -b <branch> <repo> [<folder>] $ git add <folder> .gitmodules ; + commit ; + push $ git submodule update --remote # update the submodules from their respective repo's
Typical Flow
$ git clone [remote repo] # get a local copy of the repo $ git checkout -b <branch> # start a new branch $ git push --set-upstream origin <branch> # set remote as upstream, to be able to push to remote repo # do your changes... $ git add <files> # register changes for commit $ git commit -m 'message' $ git push origin <branch> # commit the branch with changes to repo # repeat as needed... # once done with the branch $ git merge master # pull all changes from "master" $ git mergetool # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push` $ git checkout master # switch to master $ git merge <branch> # this should pass ok; commit to "master" afterwards $ git branch -d <branch> # clean up - remove the branch $ git tag <tag> <commit id> # optionally, also tag the commit after merging
Resolve Conflict
If on git pull you get a message:
error: Your local changes to the following files would be overwritten by merge: [list of files] Please, commit your changes or stash them before you can merge. Aborting
You need to resolve the conflict manually.
git fetch git add [file] git commit -m 'resolving' git merge
At which point you'll get message:
Auto-merging [files] CONFLICT (content): Merge conflict in [files] Automatic merge failed; fix conflicts and then commit the result.
Now you need to manually edit the file(s) to resolve the conflict, and then add/commit the resolved file(s).
Small Tips
Skip Retyping Your Password
$ git config --global credential.helper store
Run git pull and enter your username and password. These will be stored in ~/.git-credentials file and reused each time.
Ignoring Files and Folders
$ touch .gitignore # edit the file with your fave editor (folders should end with '/'): folder/ file.txt # it's good practice to commit the file as well $ git add .gitignore $ git commit -m "Added .gitignore file" $ git push origin master
Current Branch
git rev-parse --abbrev-ref HEAD
You can add this to .git/config as alias:
[alias] current = rev-parse --abbrev-ref HEAD
and then use it as
$ git current > master
Set meld as your difftool and mergetool
Edit your ~/.gitconfig file as follows:
[diff] tool = meld [difftool] prompt = false [difftool "meld"] cmd = meld "$LOCAL" "$REMOTE"
Now, running git difftool will bring up your dear ol' meld.
For resolution of merge conflicts, add to your ~/.gitconfig file, choosing one of the two options:
[merge] tool = meld [mergetool "meld"] # the middle file is the partially merged file, and you have to # make sense of the conflicting portions cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED" # the middle file is the "common ancestor" of the conflicting files, # and you have to choose bits and pieces to reconstruct the new merged file cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
First option turns out better in case there was lots to merge, and just bit to resolve.
The second option is better when pretty much all changes are in conflict, and reconstructing things by hand turns out easier.