git - ghdrako/doc_snipets GitHub Wiki

  • https://learngitbranching.js.org/?locale=pl

  • upstream repository - (ie the ‘primary’/reference one ) - repository (or repositories) from which source code is taken - ex github/gitlab repo

  • downstream repository - secondary - repository (or repositories) that take changes to the code from the ‘upstream’. ex local repo

As with a stream of water, if you are ‘downstream’ you receive whatever floats along the water, and you have to ‘push’ changes ‘upstream’.

Configuration

Three places stored configuration:

  1. [path]/etc/gitconfig file: This file contains all the values for every user on the system as well as all the repositories. Since this is a system configuration file, you must have administrative privileges if you want to make changes to it.
  2. /.gitconfig file: It contains values specific to you, i.e. the user. The “global” option can make Git specifically read or write to this file, which consequently can affect all the repositories you use on your system.
  3. Config file in the Git directory: This file is specific to a particular repository that you are currently using. The default “local” will make Git write to and read from this file.
  • System
git config –system
  • User
git config –global
git config –global color.ui true
git config --global core.editor emacs      # without setting git take default editor in system
git config --global init.defaultBranch main # without setting git will create a default branch called “master” 
  • Project
git config
git config user.name “Artur Kepka”
git config user.email “[email protected]”
git config core.editor “notepad.exe”
cd ~
cat .gitconfig
git config –list   # list settings from all three sources - some keys more than once because read from 3 sources
git config <key>   # show value finally using by git

Git initialize project

  • create directory to project first_git_project
cd first_git_project
git init

if you prefer to create a new repository which implements custom git-hooks, you may point to a template which is already preconfigured with custom directory structure and git-hook files to begin with.

git init --template=<template_directory>  
  • Add changes
git add .   – dodaj wszyskie zmiany w biezacym katalogu do projektu
git commit –m „Initial commit”

Counting commits

$ git rev-list - -count

Log history

List changes

git log {--oneline} {--graph} {--stat} {-n} {--before =""} {--until=""} {--author =""}
git log
git log --oneline  # show more concise history
git log --oneline -n 3 # select the latest 3 commits
git log --oneline --before="05-28-2021"
git log --oneline  --after="yesterday"
git log --oneline  --after="last week"
git log --oneline  --after="six months ago"
git log --oneline --until="one month ago"
git log --oneline MASTER~3..MASTER~1
git log --oneline --author="Altay"
git log --oneline  --grep="[Aa]nimation" # grep parameter searches for commits that have the specified string in their message. Syntax like linux grep
git log --oneline --author="Altay" --grep="[Aa]nimation" --all-match #  bez --all-match uzyskamy liste commitow pasujacych do dowolnego kryterjum a nie obu
git log --patch -S"Line1"  # -S"" search inside commits - in combination with the patch parameter, shows the places where the enquired string is changed
git log --$nazwa_funkcji  # znajdzie ostatni commit w ktorym dodano lub usunieto wywolanie okreslonej funkcji
git log --oneline --reverse # change order
git log -p -2 #  # -p wyswietla roznice w commicie -2 ogranicza do dwoch zmian
git log --oneline --stat # reports a summary of changes that happened to files
git log --oneline --graph # graph parameter helps to visualize interconection between branches



  • Bug terminal is not fully functional
cd ~
touch .bashrc
add line: export TERM=cygwin
gitk   - GUI
git status

Clone all remote branches in Git

$ git clone git://example.com/myproject
$ cd myproject
$ git branch
* master
$ git branch -a
* master
  remotes/origin/HEAD
  remotes/origin/master
  remotes/origin/v1.0-stable
  remotes/origin/experimental
$ git checkout origin/experimental
$ git checkout experimental
$ git branch
* experimental
  master
#You can actually track more than one remote repository using git remote.

$ git remote add win32 git://example.com/users/joe/myproject-win32-port
$ git branch -a

Using Git Switch

If daves_branch exists on the remote repository, but not on your local branch, you can simply type:

git switch daves_branch

Since you do not have the branch locally, this will automatically make switch look on the remote repo. It will then also automatically set up remote branch tracking.

Note that if daves_branch doesn't exist locally you'll need to git fetch first before using switch

Architektura 3 drzew

  • repository (checkout)
  • staging (commit) czasami nazywany index-em
  • working copy (add)

git init

  • --template=<template_directory> - użyj wzorca (kopiuje pliki z katalogu template)
  • --separate-git-dir=<git dir> - pozwala trzymać .git w innym miejscu. Przydatne, ponieważ .git potrafi silnie rosnąć.
  • --shared – ustawienie uprawnień

Repozytorium zdalne

bare – tworzy centralne repozytorium z którym synchronizują się klony

mkdir remot1
cd remote1
git init --bare # utworzenie repo zdalnego
cd ..
git clone remote1 local1
git status -v      #verbose pokarz co sie zmieniło
git log

Cofanie pliku z obrzaru przechowywania

git add .
git status # modified: pomiary.rb
git reset HEAD pomiary.rb  # unstage file pomiary.rb

Wycofanie zmian w zmodyfikowanym pliku

git status # unstaged modified: pomiary.rb
git checkout -- pomiary.rb  # tracimy zmiany nadpisujac je plikiem z ostatniego commit-u

Cofniecie konkretnego commita localnie

git push origin master          # origin to nazwa serwera zdalnego tego remote1 - mozna zmienic nazwe
git commit -am "test change"    # wypchniecie do repo
git reset --soft HEAD           # cofniecie commit do stagingu
git reset --mixed  HEAD         # powrot zmian do working copy
git reset --hard  HEAD          # wyrzucenie zmian

Cofniecie konkretnego commita z repo

git log               # wyswietla identyfikatory commitow - suma controlna zawartosci plikow i naglowek(jest tam data)
git log --abbrev-commit
git revert 2e5efe7    # cofamy commita ktory poszedł na serwer w odrozneiniu od git reset cofasl localne zmainy
                      # revert tworzy nowy commit ktory tworzy komot odwrotny cofa nasze zmiany
git init --bare reponame
git fetch origin master # only downloads new data from a remote repository - but it doesn't integrate any of this new data into your working files. Fetch is great for getting a fresh view on all the things that happened in a remote repository.

git pull origin master #in contrast, is used with a different goal in mind: to update your current HEAD branch with the latest changes from the remote server. This means that pull not only downloads new data; it also directly integrates it into your current working copy files.    

Konfiguracja

git config
git config -l # lista configuracji
git config --local -l
  • konfiguracja lokalna i globalna
  • hierarchia local>user>global
    • gitconfig
    • .gitconfig

Od 2.13 conditionaly includes - jesli jest w katalogu work to uzwaj takiej konfigracji a jak w home to innej

diff tool - rozwiazywanie konfliktow

Aliasy komend

git config --local alias.skrot komenda
 git config --local alias.lg1 "log --graph --oneline"   

.gitignore

logs/
*.notes
pattern*/
git config --global core.excludesfile [file]

sa narzedzia ktore generuja .gitignore dla poularnych narzedzi/frameworkow i sa referencyjne .gitignore

Blame

git blame - kto jest odpowiedialny za zmiane
git blame plik.txt # show all lines with information who modified every line
git blame -L 10,20 plik.txt - kto zmienial linie od 10-20 w pliku plik.txt zamiast przechodzic przez historie pliku

Bisect

Narzedzie do przechodzenia sekwencyjnego pomiedzy commitami zaczynajac od tego dla ktorego bylo ok aby zidentyfikowac miejsce gdzie jest zle

git bisect - identyfikacja wersji ktora wprowadzila blad


git bisect start
git bisect bad
git log # identify commite without bug
git checkout <commit-id>
git checkout main
git bisect good <commit-id>
git bisect bad
git bisect good # show commit number with the problem
git show <problem-commit-id> 
git bisect reset # show file with changes to fix
git add .
git commit -m "Fix issue"

wyszykiwanie binarne - porownuje ze srodkiem bierze jedna polowe i znowu ze srodkiem.

git bisect bad
git bisect good

Dobre praktyki

  • jak najwiecej jak najmniejszych commitów ale zeby to były spojne calosc. Łatwiej wtedy wycofywac zmiany

Branching

czyli jak mamy innego branchach i robimy commita to wskaźnik tego brancha wskazuje na nowego commita a wskaznik master wskazuje na starego commita czyli commity sa liniowo

HEAD wskaźnik na brancha na ktorym obecnie pracujemy a branch wskaźnik na commita

git branch    # list all local branches
git branch -r # list remote branch
git branch -a # list all branches (local and remote)
git branch --merged # list all local merged branches
git branch --no-merged # list all local unmerged branches
git branch -r --no-merged # list all remote unmerged branches
# ------- Deleting local branches
git branch -d <name> # branch-a usuniecie bez zmian
git branch -D <name > # force delete the branch, despite it having unmerged changes. You can use this command if you wish to permanently do away with all the commits affiliated with a specific type of development.

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d # delete all merged local branches
# ------ Deleting remote branches
git remote prune <remote> --dry-run
git remote prune origin

git push <remote> --delete <branch> # Deleting a single remote branch
git push origin --delete lint # delete the branch remotes/origin/lint.This will work for both merged and unmerged branches, but only for branches you own

git branch -r --merged | egrep -v "(^\*|master|dev)" | sed 's/origin\///' | xargs -n 1 git push origin --delete # To delete all merged remote branches
git branch -r --unmerged | egrep -v "(^\*|master|dev)" | sed 's/origin\///' | xargs -n 1 git push origin --delete
git branch -r | egrep -v "(^\*|master|dev)" | sed 's/origin\///' | xargs -n 1 git push origin --delete


git branch -v # lista branczy z info o ostatnim commit do branch-a
git branch <name> # create a new branch
git branch (-m | -M) [<oldbranch>] <newbranch> # If <newbranch> exists, -M must be used to force the rename to happen.
git branch -m <branch> # Will rename the current branch to <branch>. 
git branch -M main  # change local name of branch to main in ex because github change convention defsul name of branch from master to main


git checkout branch1 #przełacz wskaznik HEAD na branch1           
git log --graph
$ git show main:xyz # show contents of the file xyz on the main branch

Branching

  • local branch np master
  • remote remote/branch np origin/master - dowzorowanie u nas galezi zdalnej
git fetch - sciaga zmiany do origin/master ale nie do master

GitLab

  • jako Saas mozna robic prywatne repozytoria
  • lokalna instalacja

gitWeb - narzedzie do ogladania repozytorium w Web

git remote add - dodanie repozytorum zdalnego

git remote
git remote -v
git ls-remote  # wszystkie odniesienia do remotow
git remote show origin # pokaze konfiguracje remota 
git branch -r # lista zdalnych branchy
git branch -l # lista lokalnych branchy
git branch -a # lista wszystkich branchy

Mozna lokalny branch przelac na remota pod inna nazwa

git push origin branch1:branch2 # wyslanie brancha1 na remote pod nazwa branch2
git push origin branch1 # wyslanie brancha na remote
git push origin :branch1 # skasowanie brancha na remote
git svn - narzedzie pozwalajace pracowalc lokalnie gitem majac zdalne repozytorium svn

Rebase

  • kolejny poza margem sposb na integracje
  • merge tworzy nowego comita a rebase aktywnie zmienia historie moich commitów *nmarge jest bezpieczny i przy malej skali jest ok. Duzo developerów to duzo commitów margowych zaciemnajacych historie.

Nie robimy rebase commitów pchniętych na publiczne repository rebase kasuje commity i tworzy nowe !!!

odtwarza commity robione na branchu robi je na nowo na masterze przewija je maja wiec inne identyfikatory

git log --all --graph 

Workflow (model pracy)

na poczatku był chaos i tak pozostało

agile - scrum standardem

Modele

  • Feature Branch Workflow -
    • master oficjalny stan projektu
    • wszystkie zmaniy jako kolejne tymczasowe branche
    • zalety - latwo mozna testowac nowe funkcjonalnosci niezaleznie
    • jesli w feature branch pracuje wiecej osob to pcha sie go na serwer
  • Centralized
    • wspoldzielone repozytorium do synchronizacji kodu -Dictator and Lieutenants
    • model na ktorym dziala jadro linuxa
    • wielu menagerow integracji (polkownik)
    • repozytorium dyktatora jest centralnym punktem dla wszyskich
  • Integration Manager (aka Forking Workflow)
    • developerzy maja swoie publiczne klony centralnego repozytorium
    • model wykorzystywany w projektach open source
    • developerzy moga czytac czyjes klony (w GitHab nazywa sie to forki)
    • menager integracji moze wciagnac zmiany z klona do głownej linii oficjalnego repozytorium projektu (fork & pull request na GitHub), czuwa nad poprawnoscia zmiany musza przejsc przez review
  • GitFlow Workflow

W svn marge jet na serwerze w git marge musi byc zrobiony lokalnie

git fetch   # pobranie zmian do glezi origin/master ze zdalnego repo
 git log --no-merges origin origin/master # porownanie repo lokalnego ze zdalnym
git branch -r  # list branchy zdalnych

GitFlow

  • feature branchs
  • release branchs
  • hotfix branchs
git flow init
git flow feature start super-feature
git rebase develop
git flow feature finish super-feature
git flow release start v1.0

branch release jest glownie dla uzpelnienia metadanch np wersje pom.xml i changelog-abbrev-commit

branche bugfix i support doszły pozniej nie było w orginalnym modelu git-flow

Demo gitflow-a

$ git init gftest
$ cd gftest/
$ git flow init
$ git flow feature super-feature
$ git flow feature start super-feature
$ touch file1.txt
$ vim file1.txt
$ git add file1.txt
$ git commit -m "my super feature"
$ git rebase develop
$ git flow feature finish super-feature
$ git flow release start v1.0
$ echo v1.0 >> version.txt
$ git add version.txt
$ git commit -m "added version.txt set init l 1.0"
$ git flow release finish -m "v1.0" v1.0
$ git flow hotfix start v1.0.11)
$ echo fix >> file1.txt
$ echo v1.0.1 > version.txt
$ git add *
$ git status
$ git commit -m "Fixed error Updated version file to v1.0.1"
$ git flow hotfix finish -m "v1.0.1" v1.0.1

Amend

git commit --amend   - dodanie czegos do ostatniego commita np poprawa literowek
git commit --amend -m "description"

Diff

git diff {--stage} {-- {File name}}
git diff                           # By default git diff will show you any uncommitted changes since the last commit in all repo
git diff ./path/to/file            # the same as above but in specific file
git diff HEAD ./path/to/file       # By default git diff will execute the comparison against HEAD so we can ommit - the sam as above
git diff --cached ./path/to/file   # compare the staged changes with the local repository. The --cached option is synonymous with --staged.
git diff --staged -- File1.txt
git diff MASTER -- File1.txt       # compare the content of a commit in the local repository with workspace content
git diff f3db6ad..7451e37 --stat   # compare commits
git diff HEAD~2..HEAD --name-only 
git diff --name-status desc..doc # compare branchs - list files with diffs

Comparing files between two different commits

git log --prety=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body
git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a

Comparing branches

git diff branch1 other-feature-branch  # difference between two branches
git diff branch1..other-feature-branch  # difference between two branches
git diff branch1...other-feature-branch  # three dot
git diff main new_branch ./diff_test.txt # compare file between two branches

Example

vi main.go  # modify main.go
git diff
diff --git a/main.go b/main.go
index f8fcd99..18a5347 100644
--- a/main.go
+++ b/main.go
@@ -25,6 +25,7 @@ import (
        "html/template"
        "log"
        "net/http"
+       "net/url"
        "os"
        "sync"
        "time"

Git Shallow Clone

git clone --depth <depth> -b <branch> <repo_url>

git clone --depth 1 https://github.com/...git  # clome only last commit

Where:

  • depth is the amount of commits you want to include. i.e. if you just want the latest commit use git clone --depth 1
  • branch is the name of the remote branch that you want to clone from. i.e. if you want the last 3 commits from master branch use git clone --depth 3 -b master
  • repo_url is the url of your repository

Git Remote

git remote add origin URL
git remote add working URL
git push working
git remote get-url origin  # show current oringin url
git push -u origin main

Git Worktree - working with multiple branches

it is possible to have more than one work area using worktrees.

[parallax]git worktree add ../04_01b
[parallax]git worktree list 
../paralax  [main]
../04_01b   [04_01b]
[parallax]cd ../04_01b
[04_01b]cd ../parallax
[paralax]git worktree remove 04_01b
[paralax]git worktree list 
../paralax  [main]

Git Archive - create zip file from repo (even remote repo)

git archive -o "<arch file.zip>  <branch_name>  -- <folder_name>
[parallax]git archive -o "../parallax.zip" # zip entire project
[parallax]git archive -o "../parallax.zip"
[parallax]git archive -o "../parallax.zip" 02_02b 
[parallax]git archive -o "../parallax.zip" 02_02b -- build 

Restore

The add command inserts new contents into the stage area. The restore command reverts the files in two levels. With the stage parameter, the files inside the stage area are restored to their previous state, and without the stage parameter, files in both stage and workspace areas are returned to their previous state

git restore {--stage} {File name}
git restore --stage File1.txt
git restore File1.txt

For the files that are newly added into the stage area, the restore command with the stage parameter removes them from the stage area; however, it does not erase them from the workspace. So they are categorized as untracked files. The restore command is not restricted to the latest commit. Using the source parameter, one can determine which specific commit they should restore from:

$ git restore --source {commit id} {files name}
$ git restore --source bf13566 File1.txt # for example, let’s restore File1.txt from commit bf13566
$ git restore . # Let’s restore all contents of the workspace:

Reset

The reset command cancels the changes inside a commit. It works in three different levels: inside the local repository only, inside the local repository and stage area, or in all levels (local repository, stage area, and workspace). Respectively, there are three resetting options:

  • Soft
  • Mixed
  • Hard The soft reset relocates the branch pointer to a selected commit, but the stage area and working directory contents do not change. The mixed reset relocates the branch pointer and reloads the stage area with the contents of the selected commit. Finally, the hard reset reloads the stage area and workspace with the contents of the target commit.
git reset {--soft/--mixed/--hard} {commit address}
git reset --soft MASTER~1 # returns the active branch pointer one commit back

The relocation of the pointer makes the last commit inaccessible, and the branch keeps growing from the new head. After a period Git will notice this commit has no access, so it removes it from the local repository.

Revert

The reset command manipulates the history line, and it is totally fine for local repositories.

git revert {commit address}
git revert HEAD~1

Checkout

git checkout is the old command which was used to three things:

  • switch branches
  • copy files from the stage to the working tree
  • copy files from a tree-ish to the working tree From release of Git 2.23 we have new commands git switch and git restore

Using the checkout command, we can extract a set of files from a commit and restore the stage area and workspace contents.

git checkout {commit address} -- {File name}
git checkout HEAD~3 -- File1.txt #  check out File1.txt from three commits before the last one (fee2b4c) and update the workspace and stage area using the
extracted commit

Clean Untracked Files

git clean -i
git clean -fd {directory name}

Cancel a Merge

Two methods:

git reset --hard HEAD~1

git revert -m 1 HEAD

The revert command creates a new commit, which cancels the merge commit.

Remote repository

Clone

A remote repository is cloned into a local machine using the clone command.

git clone https://github.com/GitForEng/sample1.git demo01  # clone remote repo into demo01 dir

Cloning a repository automatically replicates all remote branches on a local machine. Large-scale projects have a considerable number of commits and data branches, which include only bulks of backup data. Cloning the complete project would take a lot of time and disk space.

git clone --branch feat/a --single-branch https://github.com/GitForEng/sample1.git demo02

The remote repository’s address is https://github.com/GitForEng/sample1.git; however, when the repository is cloned, Git assigns an alias name “origin” to it.

origin/feat/a semantically represents feat/a on origin and always tracks the remote branch. Additionally, Git automatically creates a local branch in the local repository named feat/a, which follows the origin/feat/a branch:

$ git branch --all
* feat/a
remotes/origin/feat/a

In this example “feat/a” is a local branch that tracks the remotes/ origin/feat/a branch. The “remotes” specifically indicates that the branch origin/feat/a follows a remote repository.

Push, Fetch, Pull

The command push calculates the changes that are required to be transferred from the local repository into the remote repository named origin. Git noticed that there was no branch in the local repository that follows the remote master branch. For this reason, it created a new branch and named it origin/master.

$ git log --oneline --all
004f6a9 (HEAD -> master) file1.txt updated
9e509ac (origin/master) file1.txt created
$ git push origin
$ git log --oneline --all
004f6a9 (HEAD -> master, origin/master) file1.txt updated
9e509ac file1.txt created

The default branch that is pushed is the current active branch (the branch that HEAD is pointed at). However, we can specify the branch name that we are interested in. For example, let’s push feat/a to origin:

$ git push origin feat/a
To https://github.com/GitForEng/sample2.git
* [new branch] feat/a -> feat/a

The feat/a branch is pushed to the remote repository, and origin/feat/a is created to follow the remote branch.

git push --all origin  #  push all branches at once
git branch --all  # list local and remote branch
git push --delete origin feat/a  # delete remote branch 
git push origin master # Git to take the changes from the master branch and synchronize the remote repository (origin) with your changes
git push origin        # as above but with current branch

Fetch

Note fetch command

  1. fetch will not update local branches. We need to update our local branches manually.
  2. fetch will not create local branches.
git fetch origin # actualize origin/master but not local master
git merge origin/master # to add change into the local branch, we need to merge the local master branch with the origin/master branch
git log --oneline --all

After this point both the local master and origin/master point to the same commit.

Pull

git pull is really two commands in one: git fetch, followed by git merge. pull command is a shortcut that engulfs both fetching and merging operations in a single command

git pull origin

Resolve conflict

git pull origin
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

After resolving all conflicts, we need to create a new commit and assign a new commit message. The extra merge commit is not the only option to integrate remote and local branches.

Another alternative is rebasing the local master branch on origin/master

git log --oneline --all
git pull --rebase origin
git log --oneline --all --graph

the rebase parameter assigns new Ids to the rebased commits. If these commits already exist in the remote repository, changing the commits’ Ids would cause confusion and even break the log integrity. For this reason, the rebased pull should only be used on the commits that are not uploaded into a remote repository.

git push --delete origin bugfix/b1 # remove the origin/bugfix/b1 branch from our local repository; also, it informs the remote repository to drop out bugfix/
b1.

Remote Connections

git remote --verbose
origin https://github.com/ghuser/Sample5.git (fetch)
origin https://github.com/ghuser/Sample5.git (push)
git remote -vv

git remote set-url origin https://github.com/ghuser/Sample6-B.git # change both  fetch and push channels of origin
# or
code .git/config

git remote set-url --push origin https://github.com/ghuser/Sample7.git # change only the push channel

We can associate several remote repositories to a local repository.

git remote add origin2 https://github.com/ghuser/Sample6-B.git # add new remote
git remote remove origin2 # remove remote
git remote add crispy8888 https://github.com/crispy8888/ideas.git
git remote -v
git fetch crispy8888
git checkout clickbait # move to locasl repo clickbait
git merge crispy8888/clickbait # marge remote clickbait to your local
git checkout master # move to local master
git merge clickbait # marge local master with local clickbait
git init demo
git remote add origin https://github.com/ghuser/Sample6-B.git
git fetch --all   # create remote tracking branches from Sample6-B.git repo but not local branches
git log --all --oneline --graph
# To get local branches to bring the files received from the remote repository into the workspace
# This is achievable by merging the local branches with their remote tracking counterpart
git merge origin/master #  command automatically creates the master branch and binds it to origin/master
# alternatively
git checkout --track origin/bugfix/a
git checkout --track origin/feat/a
git branch -vv
$git branch --all
* master
remotes/origin/HEAD -> origin/master
remotes/origin/clickbait
remotes/origin/master
$git checkout --track origin/clickbait  # get remote branch origin/clickbait to down to your machine -  tell Git to start tracking it, and witch to this branch.
$git checkout clickbait # do the same thing as above. 
Branch 'clickbait' set up to track remote branch 'clickbait'
from 'origin'.
Switched to a new branch 'clickbait'

When you specify a branch name to git checkout, Git checks to see if there is a local branch that matches that name to switch to. If not, then it looks to the origin remote, and if it finds a branch on the remote matching that name, it assumes that is the branch you want, checks it out for you, and switches you to that branch. But when remote is name diffrent then origin (in example origin2) you must use

git checkout --track origin2/clickbait

Problem with pull to empty local repo

The pull command has two phases: first, fetching the remote repository and then merging the current active branch with the remote branches.

git branch --set-upstream-to=origin/<branch> master

the local master automatically tracks origin/master. This is achieved by the --set-upstream-to parameter in the branch command:

git init demo
git remote add origin https://github.com/ghuser/sample1.git
git pull --all # error because it did not know which branch the local master should merge with.
git branch --set-upstream-to=origin/master
git pull --all # ok

Problem with push to empty github repo

$ git init demo09
$ git remote add origin https://github.com/ghuser/Sample7.git
$ git push origin # fatal: The current branch master has no upstream branch.
# To make a new branch in an empty GitHub using the push command, we can use the --set-upstream parameter like
$ git push --set-upstream origin master
# The set-upstream parameter informs Git to construct a master branch (if it is not already existing) in the origin repository.

Merge Independent Repositories

git pull origin
git log --all --graph --pretty=format:"%h %an %s" # “%h” - hash code, “%an”  author name, and “%s”  subject of the commit

pull command did not complain about irrelevant history lines. Indeed, Git downloads the remote repository contents beside the local contents.

$ git merge origin/master # The merge command refuses to merge unrelated histories.
$ git merge --allow-unrelated-histories origin/master
# after resolving conflicts
git merge --continue

Fork

Maintainers let contributors make a copy of the project for themselves (in their own accounts), which is called fork. Then ontributors start to work on their fork. When they are finished with their tasks, they send a push request to the maintainers to evaluate their fork. The request is evaluated, and if it is approved, the contributions are integrated into the original project repository.

  1. Inside the repository in github is a Fork option. By clicking the Fork button, we will have our own local copy in your github account.
  2. We clone the forked repository on our local machine
git clone --branch master --single-branch https://github.com/ghuser/syncbox.git syncbox
  1. Make changes
  2. push the local repository to our forked repository:
$ git push origin
  1. Within our GitHub account, we switch to Pull requests. By clicking the “New pull request” button, a new pull request sequence is initiated.Then we click “Create pull request” to send the request
  2. The maintainers would see the notification. After evaluation the maintainer can merge the new received request into the original data repository or reject it.

Commit Reforming

Git envisioned a list of actions to update history:

  • Squash small commits.
  • Split large commits.
  • Reword commit messages.
  • Drop unwanted commits.
  • Modify commits. Published commits should never be rewritten or changed because it could damage the other contributors’ history line So above technique apply on local commits that have not been shared with the other team members.

Reflog

log command does not consider orphaned commits or pruned branches. Deleted branches and commits are not erased from disk immediately. They exist on disk for a while, but they are not accessible.

To access deleted items, we can use reflog.

 git reflog

Garbage Collection

Git has a garbage collector tool that is responsible for cleaning the orphaned or unreachable commits. It is automatically called after special commands such as pull, merge, and rebase. Nevertheless, the housekeeping does not get into action immediately. It tarts after a timer is triggered. This is because Git wants to give the user the chance to recover the mistakes.

Domyślna wartość :

  • gc.pruneexpire 2 tygodnie
  • gc.reflogexpireunreachable 30 dni Poleceniami:
git config gc.pruneexpire now
git config gc.reflogexpireunreachable now

możemy skrócić okres przechowywania zgubionych rewizji do 0. Jeśli teraz wydamy polecenie:

git prune

Polecenie git prune trwale usuwa z repozytorium wszystkie obiekty, które nie są dostępne przy użyciu nazw symbolicznych. Polecenie to jest wykonywane jako jeden z etapów pracy polecenia git gc, które optymalizuje strukturę repozytorium. Polecenie git gc jest automatycznie uruchamiane przez niektóre komendy Git. Nigdy nie pracuj w stanie detached HEAD.

The reflogExpireUnreachable parameter of gc defines how often a non-accessible reflog entry output should be deleted:

$ git config gc.reflogExpireUnreachable now

This command adjusts the garbage collector (gc) to immediately remove inaccessible reflog entries after the cleanup process. With this format, the update is applied on the current repository only; however, to make the change for all repositories, we should add the --global parameter.

$ git reflog
d7d808b (HEAD -> master) HEAD@{0}: commit: file1.txt updated
54b8010 HEAD@{1}: commit: file1.txt updated
11dd8a9 HEAD@{2}: commit: file1.txt updated
de49853 HEAD@{3}: commit (initial): file1.txt created

To make an unreachable commit, we reset the repository to HEAD~1, so the last commit is no longer accessible:

$ git reset --hard HEAD~1

We force the garbage collector to start the cleaning operation:

$ git gc
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), done.
Total 9 (delta 0), reused 0 (delta 0), pack-reused 0

Now we check reflog:

$ git reflog
54b8010 (HEAD -> master) HEAD@{0}: commit: file1.txt updated
11dd8a9 HEAD@{1}: commit: file1.txt updated
de49853 HEAD@{2}: commit (initial): file1.txt created

After the cleanup process, the inaccessible commit, d7d808b, is deleted from the reflog history.

Amend the Last Commit

git commit --amend -m "file1.txt updated"

Id of the amended commit is changed. Git created a new commit with a new Id and assigned the new message to it.

Amend a Middle Commit

The last commit on a branch is a special one. We can change it without causing any problem for the rest of the commits on the branch.

git rebase -i 0d29dab  # i - interactive

Command Description
pick Try to use the commit as is.
reword only update the commit message.
edit amend the commit.
squash Join the commit with the previous one.
drop Delete the commit.
git rebase --edit-todo  # return to edit mode
git rebase --abort      # cancel rebasing operation
git rebase --continue   # continue with the rebasing of the next commit

Rewording a Commit Message

we can update commit messages using the rebase command we edit the To-Do list and add the reword command to the target commit

Change the Commit Order

We can change the order of commits on a branch. To do this, we need to change the commit order in the To-Do list of the rebase command.

If there were conflicts, then Git would stop the rebasing process and ask for resolving them. In this situation we can use mergetool to handle the conflicts.

Combine Commits

Using the rebase command, we can combine multiple commits in one. The command for the last commit is changed to squash to combines the last commit into the previous one.

Notes

Notes are just bits of text you can attach to a commit after it is already in the repo. A common use for notes is to explain how a commit fits in with other commits, or perhaps to flag a commit for amending or rebasing, or really to add any information you want to paste onto the commit. It does not change the commit; it is like a post-it you tack on.

git notes add -m "Remove from program.cs" bb4927c

Aliases

Aliases they allow you to create shortcuts to git commands.

git config --global alias.st status
git config --global alias.bc checkout -b
git config --global alias.cam commit -a -m
git cam "Here is my message"

git config –global alias.lg log --graph --pretty=format:'%Cred%h%Creset-%C(yellow)%d%Creset %s %Cgreen(%cr) %C(yellow)<%an>%Creset' --abbrev-commit
git lg

git config --edit --global

if you are going to use more than one flag, you must put your alias in quotes

git config --global alias.nx "log --name-only --oneline"

Submodules

Python has pip packages, JavaScript npm, and .NET NuGet packages, and many languages have their own. The native package management should be the preferred solution for sharing code across code bases. In some scenarios, such a solution might not present itself. C and C++ do not come with a native dependency management solution, for instance. In these scenarios, we can turn to Git Submodules to share code across code bases.

With Git Submodules, we add folders whose content should come from a different repository. Git Submodules uses a file called .gitmodules to keep track of paths that are submodules. This allows Git to restore the content of that folder to what we remote we have added.

$ cat .gitmodules
[submodule "katas"]
path = katas
url = [email protected]:eficode-academy/git-katas

Git Submodule configuration lives in .git/config, but as that is not shared across remotes, we need to initialize submodules to re-create the configuration from .gitmodules on new clones. This initialization is either done by git submodule init, followed by git submodule update, or git submodule update --init. The latter is preferred unless you need to customize submodule locations. Init restores configuration to .git/config, while update checks out the content to the path.

add rock as a submodule of slingshot. In the slingshot repository:

git submodule add https://github.com/<user>/rock rock

Newer versions of Git will do this automatically, but older versions will require you to explicitly tell Git to download the contents of rock:

git submodule update --init --recursive

Attributes

It is one of the places where we can fundamentally change the way Git writes objects in its internal database. They are commonly used to enforce line endings or how to handle binary files, but can also be used to convert to specific coding styles on check-in. As this is something that happens client-side, if we truly want to enforce anything, we need to implement it server- side or in automation engines.

.keep or .gitkeep

The solution to making Git recognize a directory is clearly to put a file inside of it. The usual convention is to create a hidden, zero-byte .keep file inside the directory you want Git to “see.”

create branch

https://<gerrit_url>/#/admin/projects/inv-dev,branches

git commit --date="10 day ago" -m "Your commit message" 
GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git commit -m '...'

# If it is your latest commit:
git commit --amend --date="Wed Jan 13 12:00 2014 +0100"
# If it is for example your 5th last commit
git rebase -i HEAD~5
<find the commit and change 'pick' to 'e', save and close file>
git commit --amend --date="Wed Jan 13 12:00 2014 +0100"
git rebase --continue

Add executable to git repo

C:\Temp\TestRepo>touch foo.sh
C:\Temp\TestRepo>git add foo.sh
C:\Temp\TestRepo>git ls-files --stage
C:\Temp\TestRepo>git update-index --chmod=+x foo.sh
C:\Temp\TestRepo>git ls-files --stage
C:\Temp\TestRepo>git commit -m"Executable!"

You must first remove the flag, run the git command, then put the flag back:

chmod -x <file>
git update-index --chmod=+x <file>
chmod +x <file>

then git sees a change and will allow you to commit the change.

git add --chmod=+x -- afile
git ls-files --stage
git commit -m"Executable!"

    add: add --chmod=+x / --chmod=-x options

    The executable bit will not be detected (and therefore will not be set) for paths in a repository with core.filemode set to false, though the users may still wish to add files as executable for compatibility with other users who do have core.filemode functionality.
    For example, Windows users adding shell scripts may wish to add them as executable for compatibility with users on non-Windows.

    Although this can be done with a plumbing command (git update-index --add --chmod=+x foo), teaching the git-add command allows users to set a file executable with a command that they're already familiar with.

Interactive mode

git add -p <file>

patch

This lets you choose one path out of a status like selection. After choosing the path, it presents the diff between the index and the working tree file and asks you if you want to stage the change of each hunk. You can select one of the following options and type return:
    y - stage this hunk
    n - do not stage this hunk
    q - quit; do not stage this hunk or any of the remaining ones
    a - stage this hunk and all later hunks in the file
    d - do not stage this hunk or any of the later hunks in the file
    g - select a hunk to go to
    / - search for a hunk matching the given regex
    j - leave this hunk undecided, see next undecided hunk
    J - leave this hunk undecided, see next hunk
    k - leave this hunk undecided, see previous undecided hunk
    K - leave this hunk undecided, see previous hunk
    s - split the current hunk into smaller hunks
    e - manually edit the current hunk
    ? - print help
After deciding the fate for all hunks, if there is any hunk that was chosen, the index is updated with the selected hunks.

Squash commits

Za pomoca git reset --soft cofamy sie do commit-a po ktorym commity chcemy zlaczyc w jeden - zmian trafiaja do stage i mozna wykonac git commit -m "Squash commit"

git reset --soft <sha-1 commit>
git commit -m "Squash commit"

Bezpośrednie przypisanie gałąź do commita za pomocą opcji -f

git branch -f main HEAD~3  # przenosi (na siłę) gałąź main trzy commity wstecz - za HEADa
⚠️ **GitHub.com Fallback** ⚠️