SCM GIT

Introduction

Git is a source code management (SCM) software for tracking changes in any set of files, usually used for coordinating work among programmers collaboratively developing source code during software development.

Configuration

Generic config

 ·User info:

git config --global user.email "wsparcie.t@my.dom"

git config --global user.name "Wsparcie T."

  ·Line endings normalization to LF:

git config --global core.eol lf

git config --global core.autocrlf input

... and also at repository level, in the .gitattributes file, text=auto makes that when someone commits a file, Git guesses whether that file is a text file or not, and if it is, it will commit a version of the file where all CR + LF bytes are replaced with LF bytes. It doesn't directly affect what files look like in the working tree:

* text=auto

  ·Set UTF-8 display for Git GUI differences window

# Global setting for all you repositories

> git config --global gui.encoding utf-8


# For one repository only

> git config gui.encoding utf-8


·Pull reconcile divergent branches strategy

git config --global pull.rebase false


·Tag default sort order (SemVer descending)

git config --global tag.sort -v:refname


·P4Merge difftool / mergetool

wget https://cdist2.perforce.com/perforce/r20.2/bin.linux26x86_64/p4v.tgz


gunzip p4v.tgz

tar xvf p4v.tar

sudo mkdir /opt/p4merge

sudo mv p4v-2020.2.2028073/* /opt/p4merge

sudo ln -s /opt/p4merge/bin/p4merge /usr/local/bin/p4merge


git config --global merge.tool p4merge 

git config --global mergetool.p4merge.path /usr/local/bin/p4merge

git config --global mergetool.prompt false


git config --global diff.tool p4merge

git config --global difftool.p4merge.path /usr/local/bin/p4merge

git config --global difftool.prompt false


.gitignore

# Avoid Windows streams

*:Zone.Identifier


Save username and password config

It might be useful when using HTTPS (instead of SSH).


Unsecure algternative using plaintext files:

https://stackoverflow.com/a/35942890/1323562

Note: Credentials are stored at ~/.git-credentials


Secure alternative is using GCM:

a) Install GCM

https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/install.md

Eg the 'Debian package' method

b) Configure Git to use GCM

https://aka.ms/gcmcore-linuxcredstores

Eg the 'GPG/pass compatible files' method


GitUI

GitUI provides the user experience and comfort of a git GUI but right in the terminal while being portable, fast, free and opensource.

Home > https://github.com/extrawurst/gitui'

Releases > https://github.com/extrawurst/gitui/releases

Install (tested in Ubuntu):

wget https://github.com/extrawurst/gitui/releases/latest/download/gitui-linux-musl.tar.gz

tar xvzf gitui-linux-musl.tar.gz

sudo install gitui /usr/local/bin

Verify installed version

gitui --version

Run (inside a git repo):

gitui


clone or change origin of remote repository

Clone (SSH or HTTPS)

Doc > https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-clone

git clone git@gitlab.cou.edu:COU/pera_back.git


Change origin of remote repository (eg: from SSH to HTTPs)

$ git remote -v

origin  git@gitlab.cou.dom:COU/app_back.git (fetch)

origin  git@gitlab.cou.dom:COU/app_back.git (push)


$ git remote set-url origin https://gitlab.cou.dom/COU/app_back.git


$ git remote -v

origin  https://gitlab.cou.dom/COU/app_back.git (fetch)

origin  https://gitlab.cou.dom/COU/app_back.git (push)


checkout

Handling Merge Conflicts Using "Ours" and "Theirs"

[--ours] Keep the version in the current branch:

git checkout --ours myscript.py

[--theirs] Keep the version from the branch being merged in

git checkout --theirs myscript.py


merge

Resolving conflicts using “Xours” and “Xtheirs”

In those situations where you just want to override changes from one branch to another, you can use two merge strategy options: -Xtheirs and -Xours:

[--theirs] Override the changes in the current branch w/ the feature/whatever branch

git merge -Xtheirs feature/whatever

[--ours] Keep the current branch changes

git merge -Xours feature/whatever


Force merge

Assume we want to merge hotfix/whatever to master, but that is impossible.

// go to hotfix/whatever branch

git switch (or checkout) hotfix/whatever

// create new branch

git branch hotfixtemp

// force merge

git merge -s ours master

git merge hotfixtemp


Commit & push

git gui


Create new branch from tag

git checkout -b newbranch existingtag

git checkout -b release/1.3 1.3.10


Rename branch (local and remote) [not tested]

git branch -m old-name new-name

git push origin    :old-name new-name

Switch to the branch and then:

git push origin -u new-name


Set master branch to the point of a tag [not tested]

git reset --hard v1.0


Tags

https://git-scm.com/book/en/v2/Git-Basics-Tagging

# Show list of existing tags, w/ the 1st line of the annotation

git tag -n


# Show list of the existing tags, optionally sorting by SemVer descending (config variable 'tag.sort')

git tag --sort=-v:refname


# Create tag "0.2.8"

git tag 0.2.8


# Push tags (transfer all of your tags to the remote server that are not already there)

git push origin --tags


# Push tag "0.2.8" to remote repository

git push origin 0.2.8


# Delete local tag

git tag -d <tag_name>


# Delete remote tag

git push --delete origin <tag_name>


Branches

List branches

List local branches

git branch

List remote branches

git branch -r

List all, local and remote, branches

git branch -a

Rename local and remote branch

git checkout <old_name>

git branch -m <new_name>

git push origin -u <new_name>

git push origin --delete <old_name>

Delete branch branch locally and remotely

https://stackoverflow.com/a/2003515/1323562

git push -d origin <branch_name>

git branch -d <branch_name>

Prune tracking branches not on the remote

git remote prune origin

Replace the master branch

Eg for replacing the current "master" branch with another "mybranch" branch (1st command for 'Local', 2nd for 'Remote'):

git branch -f master mybranch

git push origin +mybranch:master 

Blame

Git blame tells you who last modified each line of code in a file.

git blame app/controllers/front_controller.rb

git show <commit>

Commit anterior:

git blame <commit>~1 app/controllers/front_controller.rb

File Locking

Exclusive file locks allows you to lock single files or file extensions and it is done through the command line. Reference:

https://docs.gitlab.com/ee/user/project/file_lock.html

Install Git LFS (in your OS)

sudo apt install git-lfs

Install Git LFS (in your repository) 

git lfs install


Configure exclusive file locks

Tell Git LFS which kind of files are lockable

git lfs track "*.png" --lockable

Make sure .gitattributes is tracked

git add .gitattributes


Lock a file

Lock file

git lfs lock path/to/file.png

List files locked with LFS locally

git lfs locks


Unlock a file

Unlock file

git lfs unlock path/to/file.png

Unlock file by id (given by LFS when you view locked files)

git lfs unlock --id=123

Force file unlock (requires Maintainer permission to the project)

git lfs unlock --id=123 --force


Troubleshooting

fatal: detected dubious ownership in repository at '//wsl$/ ...

At Settings "Edit global .gitconfig" and add to [safe] the line directory = *, eg:

[user]

name = thatsme

email = thatsme@cou.edu

[safe]

directory = *


libgit2 returned: failed to get security information: Incorrect function.

This error happens in TortoiseGit, accesing a repository in a WSL path.

The solution is to upgrade the TortoiseGit version to greater than 2.14.0.0 (also works w/ Fix4009-64bit)