How to manage versions of documents and scripts from the command line. What is a work tree, staging, and commiting?. How can I go back to a previous version of a file? How to branch to test new variant without losing the functional version, how to tag the version. How to push to GitHub from the command mode using ssh authorization.
Resource
ProGit book link first three chapters are sufficient.
Git basics - repository
Initialize repository
git init
\
Add files for tracking/staging
git add [filename]
this adds a file for tracking
it also stages the already tracked file\
Commit
git commit
saves the staged changes to the files to the current branch\
Commit flags:
-a
stage all before commit. Warning: does not add files, only stages and commits.-m "text"
add the message to the commit from the command line-v
shows you the differences directly in the interface for the commit message
Usage notes
- The files you want to commit must be tracked, the -a flag will not save the day if the file has not been added already (does not have to be staged, but must be added)
- The combination
-am "message"
is useful to skip the staging area and commit all files with a short message. But I think that for me would be much more practical to keep the commits clean and do it with full control using the normal verbose patterns.
Ignore
make the .gitignore file, where you can specify the files/directories you do not want to track.
Confusing here that the .gitignore is not tracked by git add *
gitignore syntax
- “*” globing works
- “**” recursive globing also works
- ! specifies which file or pattern should be excluded from the ignoring
- character classes work
- hyphen mediated ranges in character classes work
- use /[pattern] to avoid recursivity
- use [pattern]/ to specify the directory
Branch management
git branch <new-branch>
makes a new branch\
git switch <branch-to-switch-to>
switches to a different branch
git branch
to get the list of branches
git branch -v
get list of branches with latest commits
git branch --merged
list branches you merged (and can therefore be safely
deleted)
git branch --no-merged
list branches not merged (and cannot be deleted be -d
flag`\
Rename a branch
navigate to the branch you want to rename
git branch -m <new-name>
Delete a branch
git branch -d <branch-to-be-deleted>
deletes a branch which has already been
merged
git branch -D <branch-to-be-deleted>
forces the delete even whent the branch
is not merged
Git restore back in history
git restore
removes all the previously unstaged changes.
However the staged changes are kept.
git restore --staged [file]
unstages the file
Diff
git diff
In case you want to know in more detail, what was changed between the last commit and unstaged or what is the difference between modified and staged status.
Diff between tracked and modified files
git diff
When I have all staged and committed and then modify the file, the git diff
will show me the changes in all the files I changed.
The syntax is as follows:
---
is a the origingal file,+++
is the changed file- Colour labelling:
- the white text is the text of the lines, which are not changed (there are couple of lines added for the context as I understand it)
- the red text are the modified lines as in original
- the green text art the modified lines as in the changed file.
- Apart from the colour coding, there is an
-
label to indicate the modified lines of the original file and+
label to indicate the lines which are in the modified file.
Diff between staged and commited files
git diff --staged
When using the --staged
flag, I will see the differences between the prevous commit and the staged files (destined for the next commit).
The output from the git is the same as above.
Note: --cached
flag can be used instead of --staged
it is the same.
Diff between branches to see changed files
link to an online tutorial using a new syntax
git diff --name-status <branch-one> <branch-two>
Shows the files which were changed between the different branches (the first
letter tells you what happened to it)
To understand what the letters mean, see the --dif-filter
for details
Status
git status
Tells you about the status of the changes in the current branch.
Therefore if you commited everything normally, there should be nothing in the status, and the working tree should be clean.
Status Flags
-s
adds a short form of the status in two column characters, first for notsataged, second column for staged:
* ? = untracked
* A = tracked
* M = modified
* C = commited(?)
The -s status gives you no output, when there are no uncommited changes and no untracked files.\
Removing files
All the removing of the files works in the context of the version control.
The git rm
command accepts glob character to operate on multiple files, the glob need to be escaped \*
for it to not be expanded by the shell.
The recommended example is git rm /\*~
not to track any temporary files on windows system.
Remove file from the filesystem and keep it tracked by GIT
Whenever I delete the file using the rm [file]
the file is no longer visible in the working directory and cannot be used, but is still tracked and git knows about it.\
Therefore the file is not lost forever and can be restored back using the gitrestore [file]
command.\
Tip
To see which files you deleted, just do the git status
command and you can see. You should be able to pipe it and filter out the specific file which you need to check.
Remove file from tracking by Git
git rm --cached [file]
but keep it present in filesystem.
When using the git rm --cached [file]
for the files which are already tracked by git, the file is just uncoupled from the tracking and stays in the filesystem.
Whenever you run the git status
command they will appear in the untracked section.
This change need to be confirmed by commit to keep it permanent as always.
When you run git status
you will always see it labelled as a file, which is not tracked, on the other hand the files which are specified in .gitignore file are not shown to you here.
When you run git status
you will always see it labelled as a file, which is not tracked. On the other hand the files which are specified in .gitignore file are not shown to you in the status. For both cases the files are visible in the filesystem.
Remove the file from filesystem using
git rm [file]
command.
The git rm [file]
command removes the file from the filesystem and also stages the change for the commit.
When the file was removed by the normal rm [file]
command the change is unstaged and need to be staged either by git add/rm [file]command before commit or during the fast commit
git commit -am [message]`.\
These changes can be reverted back when they are staged by using git restore --staged [file]
command. The file will still not be visible, but is present in the tracking and therefore can than be restored to its normal visibility through the git restore [file]
command.\
Moving files
git mv file_from file_to
\
I donot know if this is important or not, but the git does not really do move, it just deletes the old file, makes a new file and adds it.
looks okey to me.
When trying this in the shell looks that both the git rm/mv [file]
commands are actually staging the changes, but the normal rm/mv [file]
does get it only in the modified category so in case I just delete, I also need to add the file to be tracked and then add it to be committed.
At the end the take home message is: do it using the git commands in the terminal and you do not have to worry about it at all.\
Undoing things
To remove changes which you have not commited or staged yet:
git checkout -- <file>
\
To go to a different branch:
git checkout <branch name>
\
To go to a different commit and start a branch there to test something different:
git checkout -b new-branch-name 01d7fc
To switch there temporily (but do not start a branch lewaves uyou in a detached head nor very practical):
git checkout 01d7fc
\
SSH authorization
Resource authorization for github from gitbash
Generate ssh keys for github
- Check for existence of the ssh keys github docs link
ls -al ~/.ssh
total 36
drwx------ 2 vld vld 4096 May 19 17:24 .
drwxr-x--- 29 vld vld 4096 Aug 15 02:23 ..
-rw------- 1 root root 419 Jan 6 2024 id_ed25519
-rw-r--r-- 1 root root 109 Jan 6 2024 id_ed25519.pub
-rw------- 1 vld vld 2590 Dec 29 2023 id_rsa
-rw-r--r-- 1 vld vld 564 Dec 29 2023 id_rsa.pub
-rw------- 1 vld vld 4230 May 19 17:24 known_hosts
-rw------- 1 vld vld 3394 May 19 17:24 known_hosts.old
okey so I have the keys github_ed25519.pub and github_ed25519
Set up specific keys to be used by github in ~/.ssh/config
Host github.com
Hostname github.com
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Test that local key works
test
ssh -T [email protected]
Hi VladimirVinarsky/Learning-hugo! You've successfully authenticated, but GitHub does not provide shell access.
This notification shows that I can authorize, there is the confusing part about the /Learning-Hugo but according to chatgpt should not be a problem
Test the forwarding agent is working
echo "$SSH_AUTH_SOCK"
/run/user/1000/keyring/ssh
the varieble is set so should be okey, but if it is not, giving a response ssh-auth
needs to be activated
eval "$(ssh-agent -s)"
Test if there are identities connected with the shell
ssh-add -l
3072 SHA256:ave/RANDOM-STRING-OF-TEXT vld@pop-os (RSA)
256 SHA256:xOPMLV1Vgc/RANDOM-STRING-OF-TEXT [email protected] (ED25519)
This would be the good output
It can also say:
- there are no identities and then you need to add the keys
ssh-add <path-to-private-key>
- not able to connect to the agent then to the
eval "$(ssh-agent -s)"
again
notes:
- close and open the terminal to make sure all changes are propagated
- check that all the keys are owned by the user using the keys
Check that system allows SSH agent forwarding
ssh -vT [email protected]
not sure about this
Get the name of the key
cat ~/.ssh/id_ed25519.pub
ssh-ed25519 A-RANDOM-STUFF-HERE-1NTE-RANDOM-STUFF-HERE-WnLm-RANDOM-STUFF-HERE-IGr <email>
the ssh-ed25519
depends on the type of the algorithm used to generate the key
Add the whole string into the SSH keys in github.com
https://github/settings/keys
Working with a repo from command line and push to GitHub:
mkdir xxx
cd xxx
echo "# xxx" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin [email protected]:VladimirVinarsky/xxx.git
git push -u origin main
Make a repo on github and then push to it from command line
git remote add origin [email protected]:VladimirVinarsky/xxx.git
git branch -M main
git push -u origin main
If the authentication is set to http change to ssh
git remote rm origin
git remote add origin [email protected]:user/repo.git
Push to it
git fetch origin
git push --set-upstream origin main
Getting the repo from remote using hard reset
In case you want to replace the local repository by the remote one and not wanting to resolve all merged conflicts (by defaults tries to incorporate all changes).
git reset --hard origin/<branch-name>
git pull origin <branch-name>
*this needs to be done for each branch, when you push, only one branch gets pushed as far as I understand it"
Working with submodules
When using somebody’s else repository, can be added as a submodule. Then I can update it to the most current version, or not. I use it for the PaperMod theme for the website
# Add the submodule
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
# Initialize submodule
git submodule init
# Update submodule
git submodule update
# See the status
git submodule status
check the configuration of the submodule
in .gitmodules
[submodule "themes/PaperMod"]
path = themes/PaperMod
url = https://github.com/adityatelange/hugo-PaperMod.git
add to git and commit
git add .gitmodules
git add themes/PaperMod
git commit -m "Add Hugo PaperMod theme as a submodule"
Make sure you are on the branch and/or commit you want to be
For some reason I realized I was not on the master, so wanted to move there
cd themes/PaperMod
git switch master
cd ../..
git add themes/Papermod
git commit -m "switched to master branch of papermod"
To get to the proper commit:
cd themes/PaperMod
git checkout <commit-hash>
cd ../..
git add themes/Papermod
git commit -m "switched to <commit-hash> master branch of papermod"
Tagging
The different commits can be tagged for easier orientation between the commits.
There are lightweight unannotated and annotated tags
Lightweight tags
git tag v1.4
associates tag with the current commit
\# Listing tags
git tag
gives you the tag in alphabetical order, not in the order you put them in.
\# Searching in tags
git tag -l "v1.2*"
lists all the tags defined by the glob
Annotated tags
git tag -a v1.0 -m "my version 1.4"
in case you do not put the -m tag git starts an editor to write it in
Tagging later
To tag the commits later use the first part of hash of the relevenat commit
git tag -a v1.2 9fceb02
Sharing tags to remote repository
Git push
does not transfer the tags be default.
Use git push origin <tagname>
to achieve this.
git push <remote> --tags
In case you want to push all the tags you have to the remote repository.
Deleting Tags
git tag -d v1.4
removes the tag v1.4
The question is does it also work with globs?\
git push origin --delete <tagname>
Is the more intuitive way to delete tags on the remote repository.
git push <remote> :refs/tags/c1.4
to remove the tag v1.4 from the remote repository.
it basically means that the empty vaule before the colon is what replaces the path to the tag which is behind the colon.
Making changes to a branch and keeping the tag same
git checkout v1.4
puts you into a detached HEAD state wich is tricky, the commit will be detached from all the other branches and will be unreacheble except for the commit hash.
git checkout -b version2 v1.4
the safer way is to create a new branch based on the tagged commit version and modify that.
After that I suppose you can delete the tag and put it on the new branch after fixes.\