My Cheatsheet on git
$ git init $ git config --global user.name "John Smith" $ git config --global user.email john.smith@cisco.com $ git add switch.cfg $ git commit -m "Initial commit" $ git remote add origin https://github.com/<user>/<repo> $ git remote -v $ git push local main $ git pull
1 SCM and VCS
You can place content in source code management (SCM)
such as git. Version
control
is synonymous with SCM
. SCM is also called software configuration
management (incorrectly in my opinion). version control is also known as VCS
(version control system)
2 Version Control Systems
There are many. I have used RCS
in the past, but since Linux Torvalds
wrote git
, it's simple and powerful features have made it the defacto standard
for version control.
VCS
manages changes to a set of files, keeping a history of all those changes.
VCS
keeps these changes in a local or remote directory called a "repository".
github.com is one such, very popular, repository. There is a third type of repo
called a distributed
repo. These three vcs are called local vcs
,
centralized vcs
, and distributed vcs
3 Benefits of version control
- collaboration
- accountablity and visibility (can blame someone)
- isolation while building new features (will need to merge later)
- safe backups and restores
- work anywhere where you can get access to the repository
4 The git model
Git models history as a collection of files and folders within a top-level directory.
For example, given this tree structure on a Linux host:
~tree~ . . ├── ansible-logo.png └── foo └── bar.txt
Git labels them as follows:
- "
tree
" is a folder so in this case,foo
is a "tree", "." is a "tree" and in fact the root of the tree is a "tree" - "
blob
" is a file, so in this case,bar.txt
is a "blob"
So trees
can contain blobs
and other trees
. But blobs cannot contain trees.
The top level tree
is the directory
that is being tracked by git.
The history gives a the complete folder structure at any given point in time
.
Now, you might think that the version history is just a linear sequence of
snapshots. But git is more sophisticated than that. It models the history as
a directed acyclic graph
to model the history.
4.1 Directed acyclic graphs
Each snapshot has some number of parents. Each parent may have more than one child.
5 git datastructure
git has a model of history using pseudo code. It has three types
,
blobs
, trees
, and commits
. All git objects are one of these 3 types.
type blob = array<bytes> # an array of bytes. i.e. it is a file. type tree = map<string, tree | blob > # a folder, which is a mapping from # the filename or dictory name to the # contents, which is either another # tree (i.e. a subtree) or the file type commit = struct { # a snapshot, that is what git calls a commit. parents: array<commit> # an array of commits # not the actual commit, but pointers to the # commits. author: string # more metadata for this commit message: string snapshot: tree # is the actual contents of the commit which } # is the snapshot itself, ie the top level tree # corresponding to a particular commit.
This psuedo code comes from this youtube link.
5.1 How git stores this history in its own disk datatore?
git defines an object
, which is a blob
, or a tree
, or a commit
.
All objects are content addressed
, they are a set of objects maintained as
this content addressed store. You put it into the store via a key which is
the hash of the object. i.e. a sha1 hash of the object itself.
- remember a sha1 is a
160 bit hash
(Hexadecimal strings, 40 characters
long) (40 hex
characters is 20 bytes
which is 20*8bits
or 160
bits.)
In pseudo code, from MIT missing lecture video:
type object = blob | tree | commit objects = map<string, object> # git stores each object by first storing it's hash (id) and then the # object itself, as follows: def store(o) id = sha1(o) # the sha 1 hash of the object o object[id] = o # this actually stores to disk i.e. saves the object[id] # to retrieve an object, you need its id. so a retrieval def load(id) return object[id]
git doesn't actually store the whole tree or commit in each object. Rather
it stores pointers to the object. So you are not duplicating all these
commits
and trees
and blobs
, just pointing from one to the other to the
other.
So summariziing:
Git's on-disk datastore is a content addressable memory store where objects are addressed by their unique hash.
6 immutablitiy of git
Becauase all git objects reference previous git objects in the tree
, it does
not make sense to start changing these earlier objects. That is why the git
datastructure is immutable
. You cannot change it. You can only add to it.
You can give up all the previous changes and create a brand new git database
through the use of the git init
command. That will create a new git structure
based on the directory where you issue the git init command. (you may want to
save the .git
directory in some backup location before doing this.)
6.1 references are commutable however.
so you can change a reference
"fix bug 7" from one commit to another, but
you don't change the commit itself. The references can point to particular
nodes in a graph. and You can change them at a latter time.
7 Git in 3's
Git is organized in threes, states and stages.
- three
states
and - three
stages
7.1 git files in one of three states
A file can be in one of three states
:
modified
file has changed but has not been added to the staging area yet- in both cases the command
git add filename
transitions it to 2)
- in both cases the command
staged
file has beenadded
and ready to be committed to the repository- the command
git commit
transitions it to 3)
- the command
committed
file is saved in local repo (.git directory)
If you create a new file
in a directory that is under git control, that
file will not yet be added to git. It will be in the "normal" space
, and
appear as a UNTRACKED file in a git status output. This is a very similar
state to the modified state, in that git is not doing anything to these
files.
7.2 git's 3 stages
Files can be in (1) the repository
, (2) in a staging area
, or (3) in a working
directory
.
7.3 git staging (basically the working directory)
git has a concept of a staging area
. Any changes added to git, stay in the
staging area
. You can redo changes, make more changes etc to any files. They
still stay in the "staging" area. You can then decide what changes to include
in the next snapshot that you create. git status
will tell you what files
will NOT be included in the next snapshot by saying "untracked files"
.
The files that are "added
" to git are in the staging area. The directory
where you are working and editing files is called the working directory
. This
is NOT to be confused with the staging area.
8 git repository
On a local machine this is in fact the whole .git directory. So you will
most likely have several, half-a-dozen local repositories
.
9 master (a reference)
You can think of "master" as a pointer
to the most up to date version
of you
project. __ "master" is a reference. It is created by default when you
create the repository
, i.e. when you type git init
. By convention it refers
to the main branch of development
. i.e. the most up to date version of
your project.
Master is a reference. It is a pointer that is updated
to point to later
commits as they are committed. ha ha But true.
9.1 "head
" is a special reference.
Like 'master' 'head
' is a special reference. Head
points to the current
commit
. i.e. where you are looking right now, which might not be the latest
most up to date version. "points to" means "is referencing the hash
for a commit" Usually Head
and master point to the latest commit hash.
These are the human readable names, called references. They are mutable and as the project moves along will change and "point" to different commits.
10 git commits and status
You can commit the staged changes
, one at a time, or multiple at a time.
You can also commit only certain changes within the file
, ignoring other
changes
. A good reason why is when debugging some code, you scatter many
extra print statements to see variables at various stages of your program.
Finding the problem and implementing the fix might only take 1 line change.
It is convenient
to be able to commit just that 1 line change,
and ignore
all the extra print statments
that were only there temporarily to help you
find the bug.
(venv-xpress) [161] %git add fortune_cookie.py (venv-xpress) [162] % git commit -m "changes to DevNet training script" [master 3d58273] changes to DevNet training script 1 file changed, 14 insertions(+), 3 deletions(-) (venv-xpress) [163] % git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: ../../env_lab.py modified: ../part1/hands_on_exercise.py Untracked files: (use "git add <file>..." to include in what will be committed) ../../env_user.py~ fortune_cookie_debug.py ../../venv-xpress/ no changes added to commit (use "git add" and/or "git commit -a") (venv-xpress) [164] %
10.1 git commit messages
Either by editor, or all on one line
git commit
# editorgit commit -m "this is my commit message"
# all-in-one-line
It is important to write good commit messages. They have several features. Good commit messages follow these principles and are meant to help others, or your future self understand why some change was made. Not to neccessarily describe the change itself, because that could be done by looking at the code itself or a git diff. The message tells you why.
- short
- gives motivation, answers the question why?
- meant for future programmers
- be consistent in style through the git log
- be consistent in syntax, wrap margins, grammer, capitalization, punctuation
- be consistent in content (that is really the same as 2)
- have consistent metadata, i.e. include tracking ids? change mgt tickets?
Given these rules, a possible git log convention for an organization could be the following:
- Separate subject from body with a blank line
- Limit the subject line to 50 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line *
- Wrap the body at 72 characters
- Use the body to explain what and why vs. how
- imperative mood is used when saying "Hey you! Fix the bug" Same thing is achieved if you use: "if applied correctly, this change
will fix the bug"
Summarize changes in around 50 characters or less More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of the commit and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); various tools like `log`, `shortlog` and `rebase` can get confused if you run the two together. Explain the problem that this commit is solving. Focus on why you are making this change as opposed to how (the code explains that). Are there side effects or other unintuitive consequences of this change? Here's the place to explain them. Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary here If you use an issue tracker, put references to them at the bottom, like this: Resolves: #123 See also: #456, #789
If the change is very straightforward, then a single line is all that is needed, so skip the body. For example: "Fix typo in intro message"
See git log section, re command git log --oneline
10.2 git commit -a
Will add all the files already tracked in to a commit (without needing to add the files before). However new files will NOT be committed with -a
Typically though you probably want to control which files you put in a commit, and NOT add temporary files that you will be deleting later anyway.
10.3 git reset HEAD~1
If you want to revert this commit, you can use the git rest HEAD
command.
it will remove commit
from your local repository
and move changes
done in
that commit to your working directory
11 git Repository on a Local Machine
You can create a git repository in a local folder
which can then be
used as a source code version control system
of the programs stored in that
folder. I have been using git like this the most.
11.1 git help
You can alway type git help
at any level, for example:
git help init
git help commit
git help add
11.2 git init
This is the first step
to run within that folder. It initializes a git branch
with all the files in that folder. If the folder is empty (i.e. you are just
starting a new project) the git repository will be empty, but if there are
some files already in that folder, the repository will already be "checked
in" with those files as version 1
11.2.1 git repo
Running git init effectively creates a new repository
, for which the slang
is called "git repo
"
11.2.2 git init on Centos Linux
git init worked, but when I later added files to be committed, I could not actually do the commit. git was complaining to:
(.venv-ansible) ansible@c8host ~/Centos-ansible[343] $ git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: hosts new file: playbook.yml new file: playbooks/all-in-one-playbooks-are-listed-here new file: playbooks/ansible.cheat new file: playbooks/dnf-update.yml new file: roles/basic-utils/tasks/all-3.yml new file: roles/basic-utils/tasks/main.yml new file: roles/each-dir-is-a-role.txt (.venv-ansible) ansible@c8host ~/Centos-ansible[344] $ (.venv-ansible) ansible@c8host ~/Centos-ansible[344] $ (.venv-ansible) ansible@c8host ~/Centos-ansible[344] $ git commit *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: empty ident name (for <ansible@c8host.zintis.ops>) not allowed (.venv-ansible) ansible@c8host ~/Centos-ansible[346] $
I had to enter the two git config command, after which everything was fine.
11.3 .git directory
git init
will create a new hidden folder, .git
If you delete this folder, you will delete all the change history of the
programs in the root folder of the repository, but you will NOT delete the
programs themselves.
Because of that, git is not by itself a backup of your code. You would need
to use a remote
(i.e. github) repository to sync up your code to have a
backup. If you wish to keep files local only, you have to rely on another
mechanism of backup, i.e. time machine
that backs up the programs in the
main repository as well as the change history that is stored in the .git
directory.
You can also zip the folder
, and send it to someone
to let that person have
immediate access to your repository, changes history included. Cool!
11.4 Tracking changes
If you create a new program in the main repository, git will not itself start
tracking changes to this program. You can confirm that with git status.
You
must git add the file which moves the file into the staging area.
After which you can commit changes to that file when you are ready. You may
have to re-add the file so that your latest changes are committed when it is
time.
11.4.1 git status
This will show that you have the new program and it is "untracked
".
11.4.2 git add
Adds all untracked files into git
.
This is called "staging" were we have staged the file before a commit.
If a file is changed before it has been committed, git status will show you
two files, one already added, but another that is again "untracked".
git at this point ignores the latest changes to the file. If you commit, then
only the tracked file
is committed to git. If you want to include the
newest changes to the file, you must add
it again
, before committing it.
11.4.3 git commit
This command opens up your editor window with the changes about to be
committed. You want to edit this file so that you can add a top line
that explains what this commit is about. For example, the first time you
might say "Initial commit".
Then hit esc
and then :wq
to write the changes and quit. (if using vi)
11.4.4 git commit -m "Initial commit" readme.txt
This bypasses the editor window and adds the "string in quotes" to the top line all in one command.
11.4.5 git log
Shows who changed what, when, i.e. all the git history.
git log --all --graph --decorate
git log --graph --decorate <filename>
Almost always better to use the --all --graph --decorate
options
when using git log as it will show you the graph of the git tree.
Otherwise, git log will just show the tree as a flat linear list.
A more compact display is git log --all --graph --decorate --oneline
To see what other git log options are availble try git log --help
.
To see logs of just one file, try: git log --graph --decorate <filename>
11.4.6 git clone
If you do not want to create a new project, but rather just copy a
pre-existing project that you found on github or other repository.
The git clone
is your answer.
When a client machine clones the repository, it gets the full repository
without needing to deal with locking
, as in a Centralized Version Control
System.
After the local repository is cloned from the remote repository or the
remote repository is created from the local repository, the two repositories
are independent of each other until the content changes are applied
to the
other branch through a manual git command execution
.
Often also used to simply download some git file. You actually download the whole repository that may only contain one file. For example:
git clone https://github.com/kodecocodes/recipes.git
11.4.7 .gitignore
Keep a list of files or file types that you do NOT want included in git
version control. Files listed here will be ignored by git
Just list all the files that git will ignore
The best candidate there are
the emacs backup files # and ~. You can have a .gitignore file in each
directory. Does it also look in my home directory? Does it combine the
two files?
11.4.8 git ignore globbing patterns
.gitignore uses globbing patterns to match against file names. You can construct your patterns using various symbols:
Pattern | Example Matches | Explanation |
---|---|---|
**/logs | logs/debug.log | You can prepend a pattern |
logs/Tue/foo.bar | with double asterisk to | |
build/logs/debug.log | match directories anywhere | |
in the repository | ||
**/logs/debug.log | logs/debug.log | double asterisk also matches |
build/logs/debug.log | files based on their name & | |
NOT: | the name of the parent | |
logs/build/debug.log | directory | |
*.log | debug.log | usual |
foo.log | ||
.log | ||
logs/debug.log | ||
*.log | debug.log | patterns defined AFTER a |
!important/*.log | important/trace.log | negatting pattern will re- |
NOT: | ignore any previously negated | |
important/debug.log | files | |
debug.log | debug.log | patterns match files in ANY |
subdir/debug.log | directory | |
/debug.log | debug.log but NOT | prepending a slash matches |
logs/debug.log | files ONLY in the repository | |
root. | ||
logs | logs | If you don't append a slash, |
logs/debug.log | the pattern will match both | |
logs/latest/foo.bar | files and the contents of | |
build/logs | directories with that name. | |
build/logs/debug.log | In the example matches on the | |
left, both directories and | ||
files named logs are ignored | ||
logs/ | logs/anything | appending a slash matches a |
prod/logs/anything | directory (and all files in | |
that directory and subdir) | ||
See git ls-files section below, for important info on listing ignored and listing untracked files.
To add a file to .gitignore
11.4.9 git ls-files
To list ignored files
do:
git ls-files . --ignored --exclude-standard --others
To list untracked files
do:
git ls-files . --exclude-standard --others
If git ls-files
shows source.c
, then it must already be in the index. This
means that it is already tracked
, and possibly already committed
. If
source.c
isn't showing up in git status
at all, then the file must have been
committed.
Try modifying the file to see if it shows up as modified in git status. To really convince yourself that the file is checked in, run
git cat-file -p HEAD:source.c
to see the contents of the checked-in file (see git help
revisions for documentation about the HEAD
:source.c syntax).
11.4.10 git rm
To remove files that you do not need under git version control. git rm
only
adds the "removal" to the staging area
. It does not perform the second step
of updating the git repo itself. It also removes
the specified files from
the working directory. That it does right away.
% git status On branch master Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: pricethis-v0.1.py deleted: pricethis-v0.2.py deleted: pricethis-v1.py Untracked files: (use "git add <file>..." to include in what will be committed) pricethis-enumerate.py~ no changes added to commit (use "git add" and/or "git commit -a")
12 git commands are all just manipulations of this graph data structure.
All there is to a git repository are objects and references. They are the two pieces of data that it stores. At a high level all git command-line commands are manipulations of either the references data or the objects data.
13 branches
There is a very good explanation of branches, divergent branches and merging them at git-scm.com
In implementation, git branches are just pointers to appropriate commits.
git branches are independent from each other, with their own histories and commits. They have their own staging area, and their own working directories. When you checkout one branch, the working directory is over-written!!! with the state of that branch's files. You can flip between branches by repeatedly git checkout one branch then the other, back and forth.
13.1 Best practice w.r.t. branches
Whenever possible, one should try using branches
rather than
updating the
code directly in the master branch
. That way you can recover from edits that
break the code you already had running.
13.2 Best practices in general
The following workflow should be used in Git to be able to apply fixes to your code and develop new features:
Never
develop new features or apply bug fixesdirectly to the main branch
.Always
createseparate branch
for anew feature or bug fix
.- Apply
frequent merges of the main branch
to your feature or bug fix branch to avoid merge conflicts. - When the feature or bug fix is ready,
merge it back
to the main branch.
14 git branch
git branch
will display all the available branches as well as the branch
currently active. git branch -vv
will be extra verbose about it.
git branch covid-19
creates a new branch called covid-19, which points to
the same place where HEAD
is pointing. At this point HEAD
will point to
master as well as covid-19. (=HEAD= -> master, covid-19)
git checkout covid-19
will replace the current directory contents
with the
contents of what covid-19 is pointing to
, (which at this point is the same, so
no change really) but git log --all --graph --decorate
shows us that we are
now (=HEAD= -> covid-19, master)
ie. that HEAD
is pointing to covid-19 which is
also the same place where master is.
Now
if you start editing and adding files, the changes will be committed into
the covid-19 branch
, where HEAD
is pointing. Master will still be pointing to
the master snapshot.
any changes are committed to covid-19. i.e. (HEAD
-> covid-19) and (master)
is beside the snapshot it was on before. i.e. master stays the same
If we issue git checkout master
, the current directory is overwritten with
what was in the master commit, and HEAD -> master, Covid-19 is unchanged.
So you can flip back and forth between two developments streams.
git checkout master
git checkout covid-19
14.1 adding another branch
You can add another branch branching off of master.
- checkout master
git branch covid-plots; git checkout covid-plots
git checkout -b covid-plots
# the above 2 steps in a single shortcut.
- git log shows covid-19 where it was before, covid-plots pointing to
HEAD
and master.
14.2 git log –all –graph –decorate
Read up what each argument does. but useful command!
git log --all --graph --decorate --oneline
Is another useful ßargument to the git log command.
14.3 git branch plots; git checkout plots
This create a new branch called plots, and then switches into it at once. This can be done in one step:
git checkout -b plots
14.4 git branch -d to delete a branch
Make sure you are not on it, and that you have merged any changes you want from that branch.
git branch -d branchname
# only deletes branch if it has been fully merged
git branch -D branchname
# deletes branch using force (whatever the merge
15 git merge (opposite of branch)
After you have 1 or more branches and you want to re-combine them into the
master train, you use the git merge
.
git checkout master
# to git you back on the master train.git log --all --graph --decorate --oneline
# just to take bearingsgit merge covid-plots
If there are no merge conflicts, you are done. However if conflicts arise between master and covid-plots, a human has to decide what changes take precedence and what changes will be discarded. You will haveunmerged
paths
when runninggit status
You have to edit the file(s)
that have conflict, to resolve those conflicts, and usegit add
for each of those files, andcommit them again
. Then you are done.git merge --abort
if you get messed up, and do NOT want to do the editting at this moment. (editting of the unmerged paths that is)git mergetool
# start comparing what changes over-write each other.- if you configure git properly, you can tell it to use
vimdiff
every time you run git mergetool. OR, you can manually runvimdiff
- vimdiff
git merge --continue
to proceed where you left off to make the human conflict resolution change.
16 git merge and how it modifies the directory and the HEAD
and master references
A good explanation is available from git.scm.com
17 git checkout ( i.e. move the HEAD
pointer)
In a centralized version control system, only one person at a time
can
work on a particular file??? That seems contradictory to git merge. So what
really happens is that a user checks out a branch
, then the user can work
on that branch independently.
git checkout
moves the head
pointer AND modifies the current directory so that
it matches exactly the "snapshot" or commit that was checked out.
Also, you can run git checkout filename
and that wipes out any changes to the
filename in the directory, and replaces it with the contents of the filename at
last commit. Kind of good for a "oops daisy"
If you run git log –all –graph –decorate after a checkout, you will see that
HEAD
is no longer pointing at MASTER. It is pointing to the Checked out
commit hash.
So git checkout -b 42bf7a2
moves the HEAD
to 42bf7a2 and later, when you
want to go back to MASTER, simply git checkout master
You could also git checkout -b xxxxxx where xxxxxx is the hash of the master
commit.
git checkout
specifying a new filename will create a new branch from the
branch you are currently active on. So your workflow would be like this:
- git branch # to see if the branch isn't already there
- git checkout mynewbranch # create mynewbranch
17.1 unified diff output meaning
When run in unified diff mode
with the -u
option you get:
First two lines are
--- from-file from-file-modification-time +++++ to-file to-file-modification-time
--- from-file from-file-modification-time +++ to-file to-file-modification-time
Next come one or more chunks of differences with this syntax:
@@ from-file-line-numbers to-file-line-numbers @@ line-from-either-file line-from-either-file…
If a chunk and its context contain two or more lines, its line numbers look
like ‘start,count’
. Otherwise only its end line number
appears.
The lines common to both files
begin with a space character.
The lines that actually differ
between the two files have either a +
or a -
characters in the left print column:
‘+’ A line was added here to the first file. ‘-’ A line was removed here from the first file.
Here is a larger example:
$ diff -u 1stfile 2ndfile --- 1stfile 2020-05-22 11:32:48.000000000 -0400 +++ 2ndfile 2021-02-02 16:20:15.000000000 -0500 @@ -1,12 +1,10 @@ # The first file has twelve lines in this block # The second file ends up with only 10 lines in this block # -# macOS Notice +# macOS Notice This line was changed on the 2nd file. # # This file is not consulted for DNS hostname resolution, address # resolution, or the DNS query routing. # -# This line is in the first file, but will be removed in 2nd file -# This line also will be removed in 2nd file. # @@ -17,3 +15,5 @@ nameserver 208.67.220.220 You can get so confused that you'll start in to race down long wiggled roads at a break-necking pace +# And # Two new lines added to second file, +# On and on . # hence now we are looking at a block of 5 lines in 2nd.
18 git remote repositories
ls .git is your own git repository.
git remote
lists all of the remote repositories associated with this local
repository.
You can simulate a remote repository just by creating a different directory
and setting that up as if it was remote. In fact, you can call your
directory "github" or "gitlab" or just "remote"
Let's try with 'gitlab'.
From the git master directory:
cd ..
mkdir gitlab
cd gitlab
git init --bare
You almost never use--bare
, just read up on it later.git remote
# still have nothing there, so let's add that directorygit remote add zp-origin ../gitlabzp
zp-origin is my NAME of the remote.
18.1 git push
will send local changes to the remote repo
git push <remote> <local branch>:<remote branch>
git push zp-origin covid-19:covid-19
this sends the changes from my local branch to the remote server, on that specified branch.
git push zp-origin master:master
Every time you want to get the remote repo updated with your latest changes
you could run git push zp-origin master:master
again. However…..
git has a shortcut for this and it is by saving this parameter permanently:
18.2 git fetch
So if you have cloned a remote repository
and then want to refresh any new
files or changes from that remote repository, simply git fetch
. This will
fetch any new changes from the default repository, in our case zp-origin.
The git fetch
will download the remote repository files into your local
repository, NOT your current working directory, so there is no danger
of
overwriting files in your working directory.
If you have several remote repositories, you can git fetch <remote>
After a fetch, your local master reference will NOT have changed, so if you
like the new (more recent) changes you downloaded from the remote repo, you
can run git merge
to move your local master reference up to the latest
new changes you just downloaded.
18.3 git fetch;git merge combo
The git fetch;git merge
combo happens so often, git has made a shortcut for
this, called git pull. Actually it is more like a
git fetch
git checkout
git merge
18.4 git pull ==> same as git fetch;git checkout;git merge
You will see that you are "fast forwarding" your local repo
to be up to
date with the remote.
From developer.cisco.com this info on git pull
Local copies
of the Git repository do not automatically get updated
when
another contributor makes an update to the remote Git repository
. Updating
the local copy of the repository is a manual step. Git provides a git pull
command to get updates from a branch or repository
. git pull
can also be
used to integrate the local copy with a non-parent branch.
- The
local repository
(.git directory) isupdated with
thelatest commit
,file history
, and so on from the remote Git repository. (This is equivalent to the Git commandgit ~fetch~.
) - The working directory and branch is
updated with the latest content from
step 1.
(This is equivalent to the Git commandgit
merge
) So, you are in danger of files in your working directory being overwritten. - A single commit is created on the local branch with the changes from
step 1. If there is a
merge conflict
, it will need to beresolved
. - The working directory is
updated with the latest content
.
18.5 Remote git clone
You can download a *entire* remote repository
with all the files in it down to
a local repo by by using the git clone <url> <folder name>
So in our simulated remote repo case we can run git clone ./gitlabzp testing
which could be "cloning from the remote repo into a directory called testing"
So your local repository becomes truly like a clone of the remote repository. Usually done when you join a project that has been ongoing by remote users. Or, when you want to simply create a local repository for learning purposes, but want to start with a bunch of public code.
18.6 git config
To set up your personal preferences.
or just vim ~/.gitconfig
file (accomplishes the same as git config.)
You can also enter config commands from the command line as follows:
git config --global user.name "<user's name>"
git config --global user.email "<user's email>"
This is a requirement. Git uses this info in git blame
18.7 git clone –shallow
can be fairly big, but –shallow will only get you the master.
18.8 git add -p
This will interactively check each line of changed text
to see if you
want to include that in the commit
. Perfect for the times you have a
bunch of temporary debug print statements that you don't need to commit.
git diff
before you git add -p
will also show you all the possible changes
before you interatively stage each edit individually. so 'y' or 'n'
for each line and you are done.
18.9 typical git add -p workflow:
git diff
git add -p
- say
'y'
to a few changes,'n'
to a few changes git diff --cached
# to see what changes are due for a commitgit commit
# only the 'y' changes are committedgit checkout filename
<see note>
<note> the checkout
is needed because The local file still has the rejected
changes, so we would need to discard them
, by overwrittig the direcotry
contents with the newly committed git version
18.10 git blame
find who made the change in a give line, find who made the commit and which
was the commit that saved that line You can then see the hash (id) of the
commit and then git show 252abacef
to see all the detail of that change.
18.11 git stash and git stash pop
temporary
save some editing changes without committing them.
Suppose that you are in the middle of development, and you have not staged any
changes yet because your code is not ready to be committed. You are assigned
to a more urgent request, so you have to focus on other files, but you do not
want to lose changes that you have done so far. You can use the git stash
command to temporarily save your current changes.
Once you finish with other
work, you can then use the git stash pop
command to retrieve your previously
saved changes.
git stash list
to show you what's going on.
18.12 git bisect
Let's you automate going back through each commit to find when a version broke some function that was working before.
19 Examples of git clone
Cloning into 'coding-skills-sample-code'... remote: Counting objects: 201, done. remote: Total 201 (delta 0), reused 0 (delta 0), pack-reused 201 Receiving objects: 100% (201/201), 55.72 KiB | 0 bytes/s, done. Resolving deltas: 100% (111/111), done. Checking connectivity... done. /Users/zintis/bin/python % #+END_EXAMPLE /Users/zintis/bin/python % git clone https://github.com/CiscoDevNet/coding-skills-sample-code this downloaded the code into a folder "coding-skills-sample-code" similarly you can: #+BEGIN_EXAMPLE /Users/zintis/bin/python % git clone https://github.com/datacenter/nexus9000.git Cloning into 'nexus9000'... remote: Counting objects: 520, done. remote: Total 520 (delta 0), reused 0 (delta 0), pack-reused 520 Receiving objects: 100% (520/520), 1.14 MiB | 843.00 KiB/s, done. Resolving deltas: 100% (176/176), done. Checking connectivity... done. /Users/zintis/bin/python %
This downloaded n9K code into a directory called nexus9000
/Users/zintis/bin/python % lst total 272 drwxr-xr-x 6 zintis staff 204 9 Mar 13:15 nexus9000 drwxr-xr-x 38 zintis staff 1292 9 Mar 13:15 . drwxr-xr-x 19 zintis staff 646 9 Mar 13:04 coding-skills-sample-code
On April 2019 I cloned this:
/Users/zintis/bin/python/bin[35] % git clone https://github.com/CiscoDevNet/netprog_basics Cloning into 'netprog_basics'... remote: Enumerating objects: 133, done. remote: Counting objects: 100% (133/133), done. remote: Compressing objects: 100% (63/63), done. remote: Total 739 (delta 68), reused 132 (delta 68), pack-reused 606 Receiving objects: 100% (739/739), 368.57 KiB | 6.25 MiB/s, done. Resolving deltas: 100% (362/362), done. /Users/zintis/bin/python/bin[36] %
For detailed developer documentation, please visit https://opennxos.cisco.com/public/api
April 17th, 2019: git clone https://github.com/CiscoDevNet/python_code_samples_network.git
stored in ~/bin/python
19.1 One last real-world example with Duo TFA
/Users/zintis/git-local[10] % cd .. /Users/zintis[11] % cd bin /Users/zintis/bin[12] % git clone https://github.com/duosecurity/duo_unix.git Cloning into 'duo_unix'... remote: Enumerating objects: 9, done. remote: Counting objects: 100% (9/9), done. remote: Compressing objects: 100% (8/8), done. remote: Total 2609 (delta 1), reused 1 (delta 1), pack-reused 2600 Receiving objects: 100% (2609/2609), 1023.65 KiB | 1.78 MiB/s, done. Resolving deltas: 100% (1597/1597), done. /Users/zintis/bin[13] %
20 typical sequence of git commands
20.1 git status
should show the file as "modified"
, under "Changes not staged for commit:
"
20.2 git add filename
Also git add -A
to add all
the files in the local directory
20.3 git reset filename
To undo
a git add, before being committed.
20.4 git status
should now show the file under "Changes to be committed
"
20.5 git commit
Asks for you to edit a note explaining the changes, then commits them
20.5.1 git commit -m "you can add the note directly on the command line with the -m option"
This is a commit message, so you don't have to enter the editor at all.
20.5.2 git commit -a
This will commit all the files that were already in the git repository and that had changes. New additions will NOT be committed.
20.6 git clone
Will create a local copy of the files in the repository into the local dir.
20.7 git diff
- A minus ("-") sign at the beginning of the line refers to the state in your
local repository
- a plus ("+") sign at the beginning of the line refers to
currently made
changes
in your actual live file in the directory
git diff filename
will show you what has changed in the file specified,
compared to the file as saved in the last commit
(i.e. snapshot). Or, more
accurately, git diff filename
compares current filename to the filename
pointed to by HEAD
. So you can be explicit and say git diff =HEAD= hello.txt
To look at the diffs from earlier commits, you have to specify the hash of
that commit i.e. the commit id
20.7.1 commit id
When looking at output from git log, you will see long (x bits long) commit
ids. For example: 784f5199 50179894ffee29872faa6e170f4bc76d
. The first
32 bits
can be used as the short version
, when using commands like git diff.
For example 784f5199 for the above id can be used as its commit id
. (eight
hex characters)
git diff
will also take extra arguments that are a commit id
. So for instance
you can see what has changed from the current file compared to the file as of
3 or 4 or n commits ago. git diff *42bcdea8* hello.txt
will show difference
between the current file hello.txt on disk, and the commit named 42bcdea8.
git log --all --graph --decorate
git diff 784f519 init.el
git diff 42bcea8 init.el
This checked init.el back to two different versions.
Or you can do git diff *42bcdea8* =HEAD= hello.txt
which will compare hello.txt
from when the commit was 42bc… to what hello.txt was at the commit that
the HEAD
reference is pointing to (which might not be the MASTER) at this
point in time, and also might not be what is actually on hello.txt on disk.
The contents of the actual folder on the disk drive is what git calls
a working directory. The staging
is what has been added, but not yet committed.
If you do not supply a hash, git diff will run diff comparing the current file
to the file saved as where head
is pointing. Remember that head
is the pointer
to the LAST commit. When you start editing a file, that is not yet added to
be staged to git, the file can be changed to whatever.
git diff 42f5bc77 =HEAD= filename
will compare the difference between that
particular commit and HEAD
, vs git diff 42f5bc77
will compare to the
current file as it is in the directory (which may have had additional edits
after HEAD
)
git diff 42f5bc77 HEAD filename | current filename to version in commit 42f5bc77 |
21 man giteveryday
git comes with man pages, so man git
is a good place to start. There you will
see that man giteveryday
is another good place for beginners
22 github Hello World
Github itself has an introductory Hello World page that shows you the basics of repositories. It does NOT use the command line, but rather a web interface to git.
23 From DevNet Express
Step | Action | Git command |
---|---|---|
1 | Clone the Remote Repository | git clone <url> |
# copies the entire remote repo | ||
2 | Create and Checkout a Local Branch | git checkout -b <new branch name> |
working directory not changed but | ||
staging and commits will be onto | ||
this branch | ||
3 | Incrementally Commit Changes | git add <new or modified file> |
moves copy of file from working | ||
dir to the staging area | ||
4 | Commit all changes to the repo | git commit -m "Commit Message" |
commits all staged files to an | ||
immutable snapshot |
24 Local installation:
which git
/usr/bin/git
25 git, fish shell, oh my fish, and bobthefish theme
Keeping a long story short, using the friendly interactive shell, or 'fish' and specifically the 'bobthefish' theme, you can see the status of your git repo at all times from the commands prompt. Here is an example from feb 2020:
26 other useful git commands
26.1 git show <id>
for example git show 2097655d8d0d1737a0da7f27ff07d78e797c89e8
commit 2097655d8d0d1737a0da7f27ff07d78e797c89e8 Author: Zintis Perkons <zintis@icloud.com> Date: Sat May 9 16:38:35 2020 -0400 Improved the clarity of the internal links section in orgmode.org. diff --git a/orgmode.org b/orgmode.org index bf26b8d..005a468 100644 --- a/orgmode.org +++ b/orgmode.org @@ -133,32 +133,38 @@ It can also be specific lines in files, like my python [[file:emacs.org::*Elpy][Elpy in emacs.org]] ** adding links from specific =head=ings in other org files - When in the target org file, at the chosen link, type + When in the target org file, (or in the current file) at the chosen link, type ~C-c l~ for "org-store-link", which was previously set in init.el as follows:
but since humans don't like 40 character long names, git creates the concept of "references"
26.2 git cat-file -p <hash>
will give you information of the object that has the key specified (i.e. the
hash) For instance you can use git cat-file -p
to drill down into the git
data structure using this command.
Here's an example
ansible@c8host ~/playground/demo[1027] $ git commit [master (root-commit) d8235c4] adding hello.txt to a brand new git repository 1 file changed, 1 insertion(+) create mode 100644 hello.txt ansible@c8host ~/playground/demo[1028] $ git log commit d8235c40b7e6e78cdfe80b40339d4242ce95581f (=HEAD= -> master) Author: Zintis Perkons <ansible@zintis.ops> Date: Fri May 15 15:15:26 2020 -0400 adding hello.txt to a brand new git repository ansible@c8host ~/playground/demo[1029] $ git cat-file -p d8235c4 <<<<<========= * * * tree 9f5a7a63c2b6f9e5381cf4cfdb03b0ee55da6b9e author Zintis Perkons <ansible@zintis.ops> 1589570126 -0400 committer Zintis Perkons <ansible@zintis.ops> 1589570126 -0400 adding hello.txt to a brand new git repository ansible@c8host ~/playground/demo[1030] $ git cat-file -p 9f5a7a63c2b6f9e5381cf4cfdb03b0ee55da6b9e 100644 blob 9075408ae349c4b9df8e277ce0cd31e7c8a83156 hello.txt ansible@c8host ~/playground/demo[1031] $ git cat-file -p 9075408ae349c4b9df8e277ce0cd31e7c8a83156 hello wlrd
You can use git cat-file -p hash
repeatedly to drill down into the
tree as deep as you want. Every deeper object return you can cat-file
its hash, and keep going. Start with git log to see the most recent
changes, and get that hash and off you go.
- Sample exploration of my ~/eg repository using git log and git cat-file
/Users/zintis/eg/LINUX[72] % git log commit b943efc166be5a824735475c474ad1e640799878 (=HEAD= -> master) Author: Zintis Perkons <zintis@icloud.com> Date: Thu Jun 25 17:40:34 2020 -0400 Tweaks made during OPS335 week 1 to week6 commit 7962dee55fca0bdf5da21782736877da83e6baff Author: Zintis Perkons <zintis@icloud.com> Date: Mon May 11 00:28:14 2020 -0400 More on ansible and varied minor updates to existing outlines. commit 4104e28e081d0f14e2ee59dfa03b61dc83f73e16 Author: Zintis Perkons <zintis@icloud.com> Date: Tue Apr 14 01:19:44 2020 -0400 End of OPS335 course in April 2020 with changes in bind, mail, samba tar and CentOS networking . . . commit ca8a3b21b5331402b6fc61c5269733c0f97b920f Author: Zintis Perkons <zintis@icloud.com> Date: Tue Mar 10 13:44:03 2020 -0400 Deleted mailx.org Please enter the commit message for your changes. Lines starting . . . . /Users/zintis/eg/LINUX[73] % git cat-file -p ca8a3b21b5331402b6fc61c5269733c0f97b920f tree 4ae3e7e0fb2d77e3188fc36336a12f144d5924bb parent e859d7eb65a8f8b3e5402e9e71e5fdf04c9097f9 author Zintis Perkons <zintis@icloud.com> 1583862243 -0400 committer Zintis Perkons <zintis@icloud.com> 1583862243 -0400 Deleted mailx.org Please enter the commit message for your changes. Lines starting /Users/zintis/eg/LINUX[75] % git cat-file -p 4ae3e7e0fb2d77e3188fc36336a12f144d5924bb 100644 blob cfb28e8de267e0d9b8f842808b994f32e729ebd5 .gitignore 100644 blob d9d338f677e28b4c63eaa2a7000019e5684a46ed CentOS-network.org 100644 blob 966924a5e1cb789e1632d74337a5d26eb6a23007 CentOS.org 100644 blob 4c35c766526516ef5f24438d0fad2e1f14050731 LSCOLORS.org 100644 blob d7b002cf9afdf627fe47cf80d74a09a69f7bc247 VM-settings.org 100644 blob 1bc32d0c70c4b9d1ba502dc07ba7c086eae1fb15 apache.org 100644 blob a11e92d8403b4bfafb05b6c6a5ffa8a2ddc02aea bash-scripting.org 100644 blob 34734ba5395ee8e3138ae21376f90ee0c4812aff bind-cheat-ops335.org 100644 blob 305cf1de2f3faa132b3fff67c38525f590a2c3ea bind.org 100644 blob 492adf2503463d79a6751549123107ddd1be632c checkseq.sql 100644 blob 1f577a2f6af117533c1a2f0364ad5931ad7ff55b cron-backup.org 100644 blob 228bfdae697a867e0fc127c749dcdd08a529138b dig.org 100644 blob c2dbd392aedc0e0557bdae6a38d9fba0ec69ac1a dovecot.error 100644 blob 1056bb81528033896132aa2569f947cae0e676e7 eg-iptables.org 100644 blob 7fa6de9ce58c97aeada951a3ff0600e60e7287ce fish-cheat.org 100644 blob 7ec6277c47b27a84d9186f8ed21c3fe742a949e4 fish.org 100644 blob b18eff74cb8843db057f4734299c7ca40217756f fusion.org 100644 blob 62d585f67ed140e81538bdb1dfe7e9096866f483 =head=ers.org 100644 blob 0e3828898aed3608ade30b903b76762f09d14825 holdme.org 100644 blob 2375b802d72264de3dfd966fce1540f1cbd30dc7 html-forms.org 100644 blob 0bcf663bfa7ec79324ac27440836c6684fead8af iptables.org 100644 blob 834e1126d3bfcb8bf3cd4ecd2e1621fda6aede65 kvm-install-log.org 100644 blob b701d6ed6ca89b1f74d85f82b5e85799c19f4692 kvm.org 100644 blob 74622583fd620eb2542bfad7a9dc349f96f08cf4 lab1-net-config.org 100644 blob 72c63ca9f90d01f1901a89485ce0be61ee270b7d lab1-static-ip.org 100644 blob f294c8b424557225e3cae1a78b6c72c4a24cc111 linux.org 100644 blob 7cc0ed7c26c3c0db2696b2c07843cd409c06f533 mailx-postfix-dovecot.org 100644 blob 6ce7eabbf6b11f2c3530cf16436771a6040ebf3c mysql.org 100644 blob f95415b4125b826cdec1fecff4af37823c892a4a nat-iptables.org 100644 blob cac5fbace1e1cea6b227aa48ad570eff0c1082f6 netstat-tulpn 100644 blob 44dfe8051db1fa822070c732fdb44f5203ff6061 nmcli-ifcfg-table.org 100644 blob af4d75c86a3313d3460422c3783d8f9e9a66f36c nmcli.org 100644 blob 8bb3393635976f7ae46939f36e86c03f2242ca65 rsync.org 100644 blob 93004f6343def4f33f26162ccd5ea9e0c4c5c4a3 Samba.org 100644 blob be710b88b58fd37fe7c57a90fc61fa003b192c81 selinux.org 100644 blob d947ee05defa6afdb8e266d8052419bfd8b96d79 seneca-bash.org 100644 blob 9e698e4284ef8a39d584c5ea82cbae19bc8c3c09 Slang.org 100644 blob 19ffbf89e8873e047e34eb205a5678fad8284f8e tmux.org 100644 blob f4e9687fa045ec12bcc0b6fcbc2f7c3260067a39 top.org 100644 blob bbb5176e859d77ce587130a3c868fda261e0bcd4 trouble-shooting-mysql.org 100644 blob d6e5211733fe552e47c42518c213e3cdbb9a6a0a vanilla-etc-named.conf 100644 blob 1736be1845920d029d7157387c126215406722a4 virsh.org 100644 blob 9abeac87766e026dc340ddcc4acdcce5ae04ea3a vm1.var.log.messages.mysql.org 100644 blob f86d9d7899efdc18f8d88baf0d0d46c2605f6f6c yum-dnf.org /Users/zintis/eg/LINUX[76] % /Users/zintis/eg/LINUX[77] % git cat-file -p 9e698e4284ef8a39d584c5ea82cbae19bc8c3c09 #+STARTUP: content hidestars #+TITLE: Unix Special Character Slang #+OPTIONS: H=4 #+OPTIONS: toc:t #+AUTHOR: Zintis Perkons #+EMAIL: zintis AT senecacollege DOT ca #+DATE: <2020-01-17 Fri> * Unix Special Character Slang When using the command line in Unix/Linux, there are many shortcuts that make you efficient. Talking about command lines to others though is not efficient as many of the special characters have 3, 4 or even 5 syllables, for instance "ex-cla-ma-tion mark" has 5 syllables. The slang for that is "bang", i.e. one syllable. Here is a cheat sheet on those slangs. | Symbol | Slang | |-----------------+----------------------------------------------------| | ~#!~ | shebang, sha-bang, hash-bang, | | | #!/bin/env python | |-----------------+----------------------------------------------------| | ~!~ | bang or ping | | ~!44~ | previous 44th line | | ~!v~ | previous line starting with 'v' | | ~!v:p~ | :p to print the command without executing it | | ~!-2~ | line 2 back | |-----------------+----------------------------------------------------| | ~!!~ | bang bang | | | entire previous line, as in: sudo !! | |-----------------+----------------------------------------------------| | ~!^~ | bang-hat | | | previous line first argument | |-----------------+----------------------------------------------------| | ~!*~ | bang-splat | | | previous line all arguments | |-----------------+----------------------------------------------------| | ~!$~ | bang-buck | | | previous line last argument | |-----------------+----------------------------------------------------| | ~!$ &~ | bang-buck-snowman | | | previous line last argument as background process | |-----------------+----------------------------------------------------| | ~^~ | hat often as !^ or bang hat | | | previous line substitute delimiter | |-----------------+----------------------------------------------------| | ~#~ | hash | |-----------------+----------------------------------------------------| | ~*~ | splat | |-----------------+----------------------------------------------------| | ~$~ | ding or buck | |-----------------+----------------------------------------------------| | ~/~ | whack | |-----------------+----------------------------------------------------| | ~\~ | back-whack | |-----------------+----------------------------------------------------| | ~~~ | skid | |-----------------+----------------------------------------------------| | ~'~ | tick or prime | |-----------------+----------------------------------------------------| | ~`~ | back-tick | |-----------------+----------------------------------------------------| | ~,~ | tail | |-----------------+----------------------------------------------------| | ~"~ | dirk | |-----------------+----------------------------------------------------| | ~%~ | mod or 007 | |-----------------+----------------------------------------------------| | ~vertical pipe~ | pipe | |-----------------+----------------------------------------------------| | ~&~ | pretzel or snowman | |-----------------+----------------------------------------------------| | ~?~ | hook | |-----------------+----------------------------------------------------| | ~@~ | at | |-----------------+----------------------------------------------------| | ~(~ | open | |-----------------+----------------------------------------------------| | ~)~ | close | |-----------------+----------------------------------------------------| | ~{~ | curly or brace | |-----------------+----------------------------------------------------| | ~}~ | curly-close or un-brace | |-----------------+----------------------------------------------------| | ~+~ | plus | |-----------------+----------------------------------------------------| | ~-~ | dash | |-----------------+----------------------------------------------------| | ~.~ | dot | |-----------------+----------------------------------------------------| | ~:~ | double-dot | |-----------------+----------------------------------------------------| | ~;~ | semi | |-----------------+----------------------------------------------------| | ~<~ | from | |-----------------+----------------------------------------------------| | ~>~ | to | |-----------------+----------------------------------------------------| | ~[~ | bra | |-----------------+----------------------------------------------------| | ~]~ | ket | |-----------------+----------------------------------------------------| | ~!?~ | interro-bang | |-----------------+----------------------------------------------------| | ~--~ | dunder | | | from double underscore | |-----------------+----------------------------------------------------| | ~RETURN~ | hammer | |-----------------+----------------------------------------------------| | ~etc~ | "ett-see" | |-----------------+----------------------------------------------------| | ~regex~ | "regg-ex" NOT "rej-ex", from "regular expression" | |-----------------+----------------------------------------------------| | ~LatTex~ | "lah-tek" not "lay-teks" | |-----------------+----------------------------------------------------| | ~SCSI~ | "skuzzy" | |-----------------+----------------------------------------------------| | ~kludge~ | "kloodge" | |-----------------+----------------------------------------------------| | ~fubar~ | "eeffed up beyond all repair" | |-----------------+----------------------------------------------------| | ~foobar~ | "eeffed up beyond all recongnition | |-----------------+----------------------------------------------------| | ~ID-10-T~ | "idiot" | |-----------------+----------------------------------------------------| | ~://~ | double-dot whack-whack | |-----------------+----------------------------------------------------| | ~emacs !$ &~ | "emacs bang-buck snowman" | |-----------------+----------------------------------------------------| | ~C-r~ | Interactive reverese search. i.e. start typing | | | once on desired line, hit TAB to edit line | |-----------------+----------------------------------------------------|
26.3 references
refernces = map<string, string> Where you create a map of the 40 character hex sting to a human readable string.
The strings are what you write in a commit. A reference is also called a "pointer" They are the same thing.
The git tree and commits is immutable, but references are mutable and typically get moved from one commit to another.
26.4 git checkout -b covid-19
This is actually a shortform for two commands:
git branch covid-19
git checkout covid-19
- DANGER: git checkout changes the contents of your directory
When you realize that a checkout of a previous branch it
- moves the
HEAD
pointer back to that earlier commit, and - it must also then change the contents of the current directory, because that is what was 'current' in the older commit.
As long as you realize that, you will be ok. You can always move the pointer forward (and back to the MASTER) commit using:
git checkout master
Always check where you are with git log –all –graph –decorate whenever you checkout a commit.So any changes that have not been committed to git will be LOST.
- moves the
26.4.1 git checkout -b
The -b is for branch and it causes Git to create a new branch - and then switch to it.
26.5 Customer references
You can create custom references, which as all other references are, are simply labels attached to a git hash.
27 Under the git repository folder, you can:
27.1 git pull
pulls down the files from the remote git repository
27.2 git push
will send the locally modifed file to the remote git repository
28 magit
diredmode, type
M-x magit
Here is a screen shot of my magit page in ~/bin/python/bin
28.1 magit-mode commands:
<tab>
to expand sections OR to expand a filemagit-section-toggle
hammer
magit-visit-thing
?s
on an untagged file, to stage it.magit-stage
u
on a stagge4d file to unstage it.magit-unstage
?
show available commands.magit-dispatch
q
to quit this command displayc
commitmagit-commit
c
commitmagit-commit-create
(c is entered twice )b
branchmagit-branch
b
b again which ismagit-checkout
( b is entered twice )s
spin off a branchmagit-branch-spinoff
l
logmagit-log
l
logmagit-log-current
(l is entered twice)q
quit this command (magit-log-bury-buffer
)w
magit-amw
magit-am-apply-patches (w is entered twice)C-c C-c
to close the edited commit.SPC
show a magit diffmagit-diff-show-or-scroll-up
0
show magit diff defaultmagit-diff-default-context
1
show section level 12
show section level 23
show section level 34
show section level 4:
magit-git-command<
beginning of buffer>
end of buffer
So a typical, basic magit workflow is: M-x magit
s
-s
|- or all changes withS
s
-c c
Make your editing changes, then C-c C-c
actually I think it's C-c c
Find out which one.
$
bring up the details of the error message that just appeared.P
push your commit o repository i.e. github
28.2 magit status
M-x magit-status
(you can set C-x g
to map to M-x magit-status by using:
(global-set-key (kbd "C-x g") 'magit-status) in your .emacs-d/init file
Refres (g/G) global-magit-file-mode (C-c M-g) magit-dispatch (C-x M-g)
First a good idea to confirm that C-x g is not being used by anything useful
C-h k C-x g
See help magit status section above.
? will display the magit commands availale. (must be in the magit-status buffer)
M-n/p, j to move around the git status window (next/previous) M-1 or -2 or -3 or -4 , TAB, S-<tab> for visibility
28.3 magit diff options
D C-c C-t (or M-x magit-diff-trace-definition) ?
Once in the diff buffer (D) see toggles such as -U for context lines and -t for hunk refinements which can show you the actual changes made to files between git commits.
git diff –word-diff (is the equivalent git cli command.
In a diff buffer, you can get the function history list as well… That is a list of historic changes to the function you are currently looking at say in python, or in .php or whatever program is being edited in magit mode.
28.4 Logging options in magit
L can toggle dates from absolute dates or days or hours ago.
28.5 magit blame
shows who and when people committed people.
28.6 close the magit buffers with letter 'q' for quit
28.7 magit stage and unstage with a single letter
$ will show you what is happening with your git commands, at any time you want.
- to show dates when lines or sections were added or changed or deleted from a git file.
28.8 magit commit
c -e allow empty commit -a stage all modified and deleted files –all
- v show diff of changes to be committed
- M-n or M-p can browse through past commit messages. (once in the commit buffer) i.e. have hit c
You can also C-c C-a to commit ammend (see docs for all the options of C-c C-a to commit ammend.)
28.9 magit insert git =head=ers C-c C-r, C-c, C-s
28.10 magit branching
b brings up the branch popup. Can create a new branch, or open a branch, can check it out or not in the same command.
28.10.1 spin-off
Let's say you are working on a branch for a couple of hours, making lots of edits, and make a few commits, when you realize, "oops, I should not be making these commits to master!". What to do? If you have made a couple of commits but have not 'pushed' it yet you can:
hit b
and s
which will spin
off a new branch
.
It will reset
the master head
back to where you were when you started, take the several
commits you have done today
, and spin off new branch
, applying those editting changes
on this new branch. All automagically. Thus saving your bacon.
You can spin off of any branch.
28.11 Reverting (V)
V VV (magit-revert-and-commit) Vv (magit-revert-no-commit)
28.12 resetting (X)
Read the docs on this. What follows is just to make you aware that this feature exists, and is fairly useful:
Get your mouse onto a recent commit (pick one) and hit:
x (and type Head
) to revert to that version. ?
x (and bring up the log to see what version you want to revert to.)
28.13 Stashing (z)
z z (magit-stash-both) Stashes index and working tree, untracked files included.
Once a change is stashed, you can hit a on the stash (under git status buffer) at a latter time, to then incorporate the change into the branch at that time.
28.14 Rebasing (r)
r i (magit-rebase-interactive) Rebase allows you to resolve conflicts and rewrite history. ** very useful
magit does this very well.
Look at the log, choose a commit where you want to start the rebase. hit r i For instance c76309r then you will see a list of commands. Read them and use C-c C-c to execute what you want with the rebase. - any errors will pop up for you to resolve, or skip and continue forward.
C-c C-k to kill buffer out of this if you do not want to make any changes.
28.15 Bisectting
B B (magit-bisect-start) B s (magit-bisect-run) B b (magit-bisect-bad) B g (magit-bisect-good) B r (magit-bisect-reset)
This is good if you have a bug and want to know when the bug came into being.
Works good if you have been following proper git etticat, hygene and standards, with proper messages left on commits, etc.
28.16 Rebasing
Read up on this.
28.17 others: magit-tag, magit-notes, submodules, worktree
29 Study topics for Cisco 900 cert
1.8.a Clone
git clone <url>
1.8.b Add/remove
git add <new or modified files>
1.8.c Commit
git commit -m "Commit message"
1.8.d Push / pull
The git pull command is used to fetch
i.e. download, content from a remote
repository and immediately update the local repository to match that content.
The git pull
command is actually a combination of two other commands, git
fetch
followed by git merge.
In the first stage of operation git pull will
execute a git fetch scoped to the local branch that HEAD is pointed at. Once
the content is downloaded, git pull will enter a merge workflow. A new merge
commit will be-created and HEAD updated to point at the new commit.
git push
# will send the locally modified files to the git repository
git pull
# will receive a copy of the latest version from the git repository
1.8.e Branch
git branch
will display all the available branches as well as the branch
currently active. git branch -vv
will be extra verbose about it.
git branch covid-19
creates a new branch called covid-19, which points to
the same place where HEAD is pointing. At this point HEAD will point to
master as well as covid-19. (HEAD -> master, covid-19)
git checkout covid-19
will replace the current directory contents with the
contents of what covid-19 is pointing to, (which at this point is the same, so
no change really) but git log --all --graph --decorate
shows us that we are
now (HEAD -> covid-19, master) ie. that HEAD is pointing to covid-19 which is
also the same place where master is.
Now if you start editing and adding files, the changes will be committed into the covid-19 branch, where HEAD is pointing. Master will still be pointing to the master snapshot.
any changes are committed to covid-19. i.e. (HEAD -> covid-19) and (master) is beside the snapshot it was on before. i.e. master stays the same
If we issue git checkout master
, the current directory is overwritten with
what was in the master commit, and HEAD -> master, Covid-19 is unchanged.
So you can flip back and forth between two developments streams.
git checkout master
git checkout covid-19
1.8.f Merge and handling conflicts
git merge
is the opposite of git branch.
After you have 1 or more branches and you want to re-combine them into the
master train, you use the git merge.
- git checkout master # to git you back on the master train.
- git log –all –graph –decorate –oneline # just to take bearings
- git merge covid-plots If there are no merge conflicts, you are done. However if conflicts arise between master and covid-plots, a human has to decide what changes take precedence and what changes will be discarded.
git merge --abort
if you get messed up.git mergetool
# start comparing what changes over-write each other.- if you configure git properly, you can tell it to use
vimdiff
every time you run git mergetool. OR, you can manually runvimdiff
- vimdiff
git merge --continue
to proceed where you left off to make the human conflict resolution change.
1.8.g diff
git diff filename
is the same as saying git diff HEAD filename
i.e. it
compares the current file to the file as it was in the last commit.
Similarly git diff 42bcdea8 main.py
will compare the current main.py file
to the state it was in the commit identifited by commit-id 42bcdea8
zp: checkout
gitcheckout -b <new branch name>
git checkout covid-19
will replace the current directory contents with the
contents of what covid-19 is pointing to, (which at this point is the same, so
no change really) but git log --all --graph --decorate
shows us that we are
now (HEAD -> covid-19, master) ie. that HEAD is pointing to covid-19 which is
also the same place where master is.
1.5 Explain the benefits of organizing code into methods / functions, classes, and modules 1.6 Identify the advantages of common design patterns (MVC and Observer)
1.7 Explain the advantages of version control 1.8 Utilize common version control operations with Git
- a Clone
- b Add/remove
- c Commit
- d Push / pull
- e Branch
- f Merge and handling conflicts
- g diff
30 TODO Graphical overview of git processes.
See youtube on git rebasing for idea to document git checkout, branch, merge and rebase.
31 Good overview of git
From stackoverflow.com :
The index / staging-area In a normal Git repository, there are three items of interest with regard to each file.
- There is the file's state in your current (or
HEAD
) commit. - There is the file's state in your work-tree, where you can edit the file with your favorite editor(s), run any normal commands on it, and so on.
- There is the file's state in Git's index, also called Git's "staging area".
The staging area is, in essence, "what will go into the next commit you
make". Remember that in Git, every commit is a complete snapshot of your work:
every file that is staged (or "tracked", i.e., is not an "untracked file") is
recorded exactly as it appears in the staging area. Once you make the commit,
the staging area matches the commit you just made. It's not empty. It's full of
files
But a git diff that compares the commit to the index will be empty,
because the index and the commit contain the same stored-up work-tree. If you
then modify a file in the work tree and git add it, Git replaces the index
version with the work-tree version, so that now the index and the HEAD
commit
differ.
git status and git diff With that in mind, let's take a look at your specific git diff command, and the git diff documentation. You ran:
git diff origin/newbranch – local-path/test.cs The documentation says, in part:
git diff [–options] <commit> [–] [<path>…] This form is to view the changes
you have in your working tree relative to the named <commit>. You can use
HEAD
to compare it with the latest commit, or a branch name to compare
with the tip of a different branch.
This means you were comparing the work-tree version of local-path/test.cs against the version in the commit at the tip of origin/newbranch.
The index version of the file has no part in this comparison.
Now let's look at what git status diffs. These quotes are still from the git diff documentation:
git diff [–options] –cached [<commit>] [–] [<path>…] This form is to view
the changes you staged for the next commit relative to the named
<commit>. Typically you would want comparison with the latest commit, so
if you do not give <commit>, it defaults to HEAD
. If HEAD
does not exist
(e.g. unborn branches) and <commit> is not given, it shows all staged
changes. –staged is a synonym of –cached.
You can safely ignore the slightly odd notion of "unborn branch" here. This
compares a specific commit versus the index. By default, it compares HEAD
vs the
index. This tells you what would be different in a new commit.
This is the first diff that git status does, to find out what you would commit if you committed now.
We also find, in the git diff documentation, this:
git diff [–options] [–] [<path>…] This form is to view the changes you made relative to the index (staging area for the next commit). In other words, the differences are what you could tell Git to further add to the index but you still haven't. You can stage these changes by using git-add(1).
In other words, this compares the index to the work-tree. Whatever shows up as different here, you could git add to your index, so that it shows up in the first diff that git status runs. Instead, it currently shows up in the second diff that git status runs.
After git status has run these two diffs, it prints any files that showed up in
either one, as "changes staged for commit" or "changes not staged for
commit"—or, in some cases, both. (For instance, you can add a line to README and
stage that, then add another line to README but not stage it yet. Now you have
changes from HEAD
to index—the first line you added—and changes from index to
work-tree: the second line you added.)
Again, git status reports all of these. You say it is reporting nothing: this
means that your HEAD
commit matches your index, and your index matches you
work-tree. There is one special case to consider before we move on.
For untracked files—which are by definition not in the index and not in the HEAD
commit—git status normally reports them as "untracked files". This is often more
annoying than useful, so you can use .gitignore to tell git status to shut up
about these files. Check your .gitignore to see if it is ignoring
local-path/test.cs. Presumably it is not, but if it is, that could be the reason
you would not see anything.
Putting it all together You also say that if you git diff origin/newbranch – local-path/test.cs, you do see differences. This means that your work-tree does not match the commit to which origin/newbranch points.
From git status (and assuming no .gitignore action), we know that the HEAD
and
work-tree versions of local-path/test.cs are the same. And, we see that the
origin/newbranch version of local-path/test.cs are different. We can therefore
conclude that the HEAD
version is not the origin/newbranch version: these must
be two different commits.
This is a perfectly normal state. Sometimes git status does report something else for this state, though.
Upstream branches Specifically, each branch can have an upstream branch. No branch is required to have an upstream branch, and there is no constraint on the form of the upstream branch if there is one, but every branch can have one—and only one—upstream.
Normally, a local branch like master or newbranch usually has a remote-tracking branch like origin/master or origin/newbranch as its upstream.
The existence of the upstream is, again, optional. But if there is one, git status uses it to compare the current branch against its upstream.
Specifically, if newbranch has origin/newbranch set as its upstream, and if—as we believe we have just proved—newbranch and origin/newbranch differ, git status will tell us that one branch is ahead of the other, or behind the other, or both. (The git status command does this by comparing the commits—not their contents, just the commits themselves—that are reachable from the two branches. I'm not going into any further detail here; for much more on this, see this answer.)
None of this can happen unless the current branch has an upstream set.
You wrote that you ran:
git checkout -b newbranch This form of git checkout creates a new branch, and by default, does not set an upstream for it.
To set an upstream, use git branch –set-upstream-to (see the documentation for git branch for details).
Note that git checkout name, when name does not currently exist as a local branch, but origin/name does exist, will create the local branch name with its upstream set to origin/name. This is very different from git checkout -b, which creates a local branch with no upstream set (and often a different starting value for the branch tip).