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:

  1. -a stage all before commit. Warning: does not add files, only stages and commits.
  2. -m "text" add the message to the commit from the command line
  3. -v shows you the differences directly in the interface for the commit message

Usage notes

  1. 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)
  2. 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

  1. “*” globing works
  2. “**” recursive globing also works
  3. ! specifies which file or pattern should be excluded from the ignoring
  4. character classes work
  5. hyphen mediated ranges in character classes work
  6. use /[pattern] to avoid recursivity
  7. 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:

  1. --- is a the origingal file, +++ is the changed file
  2. 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.
  3. 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 commitgit 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

link1

link2 generate ssh keys

Generate ssh keys for github

  1. 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.\