Skip to content

gitBook

holzkohlengrill edited this page Dec 15, 2023 · 44 revisions

Summary

  1. Summary
  2. Commands
  3. Remotes
    1. HTTPS > SSH or vice versa
  4. Repo
    1. New
      1. No local data
        1. Cloning via https
        2. Cloning via ssh
      2. Existing local data
    2. Split subfolder of a repository into a separate repository
    3. Merge two repositories together for the same project
  5. Contribute
    1. Basic Workflow
    2. Stashing
    3. Move local commits to a branch
    4. Review changes before commit (show uncommitted changes)
    5. Pull request workflow
    6. Staying up-to-date
    7. Damn! I forgot something in my commit message
      1. Unpushed commits
      2. Pushed last commit
      3. Pushed commit which is not the most recent
      4. Misc
    8. Undo a reset
    9. Mark files back as unstaged (undos last commit message!)
    10. Uncommit pushed file
    11. Rebase
      1. Feature branch on master
      2. --onto
  6. Branches
    1. Clone one single branch
    2. Enter/change/switch to branch or to a specific commit
    3. Merge branches
      1. Merge master into feature branch (update feature with master's state)
    4. Delete branch
    5. Clean-up local branches deleted on remote
  7. Submodules
    1. Add a git submodule
    2. Get submodule contents after super repo checkout
    3. Update commit status of submodules in super repo
  8. Merging
    1. Fast-Forward
    2. Resolve merge conficts
      1. What you have locally
      2. What was introduced by the other commit
      3. Merge conflict workflow
  9. SSH
    1. SSH on Windows
    2. Rewriting the History
      1. Filter branch
        1. Copy a folder (including its history) from a repository to another
    3. GitHub related
      1. Issues
      2. Search

//////////////////////////////////////////////////

This snipped needs clear rework. This does not suit our quality standards.

//////////////////////////////////////////////////

Commands

  • blame : who has change what
  • git rm --cached mylogfile.log or for directories git rm --cached -r mydirectory : Remove file wihtout deleting local copy
  • git push origin branchname : push to origin repository. No requirement to name the remote repository origin: in fact the same repository could have a different alias for another developer
  • git mv : like the normal mv -> rename and/or move files (safer and better than just mv)
  • Get total commit count of an already checked-out repo: git log --oneline --all | wc -l (last one is a lowercase L)

Remotes

remotes are simply an alias storing the url of repositories. Origin (widely used) is just a name (the alias).

Show available remotes:

git remote -v

origin	git@github.com:holzkohlengrill/blahblub.git (fetch)
origin	git@github.com:holzkohlengrill/blahblub.git (push)

Push to an origin: git push origin master

HTTPS > SSH or vice versa

If you want to switch from https to ssh you need to change your origin/remote (or add a new one). Basically you modify an existing origin

git remote set-url origin https://github.com/USERNAME/REPOSITORY.git

Adds a remote named origin: git remote add origin https://github.com/user/repo.git.

Removes/deletes a remote named origin: git remote remove origin

Repo

New

No local data

Cloning via https

git clone https://holzkohlengrill@bitbucket.org/holzkohlengrill/yourRepo.git myMightyFolderNameForMyProject

Cloning via ssh

git clone git@github.com:WHOEVER/WHATEVER.git PROJECTNAME

Existing local data

cd existing_folder
git init                # Initialise git "env"
git remote add origin https://github.com/TeamFlowerPower/kb.wiki.git   # Add repo URL to remotes
git add .               # Add all files
git commit              # Commit files to repo
git push -u origin master   # Push and set upstream (-> `-u`)

Split subfolder of a repository into a separate repository

Follow this guide: https://docs.github.com/en/free-pro-team@latest/github/using-git/splitting-a-subfolder-out-into-a-new-repository

Basically you apply git filter-branch on the desired branch and (sub)folder, change the origin and push to the new repository:

  1. Filter: git filter-branch --prune-empty --subdirectory-filter dir/to/keep/ branchToKeep
  2. Check: git log
  3. Create new repository and add it as the new origin: git remote set-url origin git@new-repo.org/repo.git
  4. Check: git remote -v
  5. Push: git push -u origin branch

Merge two repositories together for the same project

Say you have an old repository and due to infrastructure it gets pushed to a new one but without preserving the history. You want to combine those two afterwards.

old repo:   A-B-C-D-E
new repo:             F-G-H-I-J-K

combined:   A-B-C-D-E-F-G-H-I-J-K

How this is done is described here


Contribute

Basic Workflow

  1. add >> wildcards work as well: e.g. git add mypath/VL*/*yaml (>> note, if you put single quotes, it prevents the shell from expanding the wildcard and might produce unexpected results, also depends on how or whether or not your shell is expanding wildcards)
  2. commit
    • partial commit: git commit -m "<message> #-> dot after this message is important!!" .
  3. push >> apply changes
git add contributors.txt    # add a file or folder
git commit -m 'Initial commit with contributors'   # -m : message; -a : all (Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.)
git push origin master    # origin: default remote by git clone, master: default branch; push either by remote(origin master) or url(git@github.com:git/git.git master)

You can do an interactive commit with:

git commit -p               # patch
# or
git commit -mp "Some commit message"

-> You might want to select only parts of the file to be committed. For the available commands see the table below:

Abbreviations:

Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ?
y - stage this hunk
n - do not stage this hunk
a - stage this and all the remaining hunks in the file
d - do not stage this hunk nor any of the remaining 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

Stashing

You may have changes that you want to "save" for later. Git stash works like a stack.

# Save you work (push to stack) and reset to the last clean state
git stash

# View stash stack
git stash list

# Get back saved state from stash (pop from stash stack)
git stash pop

# Name a stashed state
# Starts an interactive prompt to select hunks for stashing (choose what to stash)
git stash save -p "Name of your stash"
#              ^^---- print diffs + starts interactive session (can be ommitted if you only want to give it a name)
Cmd Description
y stash this hunk
n do not stash this hunk
q quit; do not stash this hunk or any of the remaining ones
a stash this hunk and all later hunks in the file
d do not stash 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

Move local commits to a branch

We assume you are currently on master.

  1. Apply potential changes from origin/master to your (modified) master branch git rebase origin/master (use rebase to avoid merge commits)
    1. If there are merge conflicts fix them and continue with git rebase --continue -> creates a merge commit in this case
    2. If the conflicts are to bad stop (git rebase --abort) and try a merge instead
  2. Create the new branch: git branch myNewBranch
  3. Reset your master back to origin/master: git reset --hard origin/master
  4. Check the log of your branches if you did everything correct then push your branch

Review changes before commit (show uncommitted changes)

git diff

Pull request workflow

  1. Fork and clone the repo where you want to contribute
  2. Create a local branch for your changes
  3. Make, commit and push your changes to your local branch
  4. On the web page for the upstream repo go to the pull requests tab and click on "New Pull Request"
  5. Select the branch you want to submit to
  6. Describe your changes (what problem does it solve, user-visible impact, how did you solve it)

Staying up-to-date

Command Description
git log shows last commits (+metadata)
git log --name-status Show changed files and their status per commit
git whatchanged -p or git log -p Show textual diffs of last commit
git whatchanged shows changed files + commit messages

To see commits of one specific author you can use both options with the --author="<commiters-name>" argument. You don't have to state the complete name.

Damn! I forgot something in my commit message

Unpushed commits

git commit --amend                 # Opens the default editor for editing

Pushed last commit

  1. git commit --amend (an editor will open -> modify the commit message; save & close)
  2. git push --force

Pushed commit which is not the most recent

  1. git rebase -i HEAD~4 (say you want to edit the 4th commit message you see in git log)
  2. An editor will open: change pick to r (editing the commit message at this step has no effect; you will see a short command reference in the editor as comments); close the editor
  3. Another editor will open: here you can modify the commit message; close the editor
  4. git push --force

-> git reflog might be of use here

Change author and email address

  1. git rebase -i -p HEAD~4 (say you want to edit the 4th commit message you see in git log)
  2. git commit --amend --author "New Name <new-email@address.com>"
  3. git rebase --continue
  4. git push -f

-> git reflog might be of use here

Misc

  • git reset --soft HEAD~1: Throws your last (local) commit away (make sure you're on HEAD)
  • git reset --hard HEAD~1: Throws your last (local) commit away and reverts all your local changes to the last commit (make sure you're on HEAD)
  • git add ./blah && git commit --amend : Include a file to your last commit (i.e. if you have committed only for one file but forgot another which matches you commit message)

Undo a reset

This is also useful if your rewrote the git history (locally) and want to undo the rewrite (just checkout the hash from git reflog).

See history:

$ git reflog
07540e8 HEAD@{0}: checkout: moving from gen4-1 to master
cdc974c HEAD@{1}: reset: moving to HEAD
cdc974c HEAD@{2}: reset: moving to HEAD@{5}
b15c929 HEAD@{3}: reset: moving to HEAD~1
cdc974c HEAD@{4}: reset: moving to HEAD~1
185ac8a HEAD@{5}: reset: moving to HEAD~1
46c49ef HEAD@{6}: revert: Revert "Added Smart Algo for UDP client"
185ac8a HEAD@{7}: pull origin master: Merge made by the 'recursive' strategy.
cdc974c HEAD@{8}: cherry-pick: Map: added json output/conversion to duplicate finder
b15c929 HEAD@{9}: checkout: moving from master to gen4-1

Go to specific point in time:

git reset 'HEAD@{1}'

Mark files back as unstaged (undos last commit message!)

See here

Uncommit pushed file

You are on a branch (!*) and accidentally committed and pushed a file modification.

  1. Checkout the original file state (in this case it's master): git checkout master ./path/to/file/to/reset
  2. Commit the change: git commit -m "Reset master state of irrelevant file" . (the message is not so important since it will be removed later on)
  3. Do interactive rebase for the last x commits (here: 4): git rebase -i HEAD~4
    1. A text editor opens; For the commit of step 2:
      1. Make sure you move the commit after the one introducing it (latest commits are at the bottom)
      2. Change pick to squash
    2. Save and close the editor
  4. Check if everything went fine (-> git status, git log, git whatchanged, git log -p)
  5. Force push: git push --force or git push --force-with-lease

* Works also on master but this solutions uses a force push which is only recommended on non-shared branches (-> not master); read also about the (force push with lease option)[https://salferrarello.com/never-git-push-force/]

Rebase

Nice article about rebase: https://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/

Feature branch on master

We assume that we are currently on the feature branch and want to rebase on top of master.

  1. git fetch # get current state
  2. If there is something to commit: git commit -m "blahMessage" .
  3. git rebase origin/master # Put my changes ontop of current status/changes (on server)
  4. git push

A visualisation can be found here.

See also: https://blog.algolia.com/master-git-rebase/

--onto

git rebase --onto <newbase> <oldbase>

Branches

git branch                        # all available branches
git branch <newBranchName>        # Creates new branch >> Note: This does NOT enter the branch
git branch -a                     # all available & deleted branches
git branch -r                     # all removed branches
git push -u origin <branchName>   # Push branch to remote

Output example of git branch -a:

    * master
      dev
      remotes/origin/HEAD -> origin/master
      remotes/origin/master

* inidcates current branch

Clone one single branch

Maybe helpful (not checked/tried) http://stackoverflow.com/questions/1778088/how-to-clone-a-single-branch-in-git

Enter/change/switch to branch or to a specific commit

git checkout <branchName>
git checkout <commit-hash>                                # Switch to the state after that specific commit
# e.g.
git checkout e442f37a10291a7d93fd9c5068b4e10f554738ed

Works also for individual files (checkout is only applied to the current path, so, be aware of this):

Revert by checking out latest commit or master.

Merge branches

git merge <branchName>

Combines the specified branch’s history into the current branch

Merge master into feature branch (update feature with master's state)

This is useful when you want to test or integrate your changes with the current state of the master branch.

git merge feature master
#         <into>  <from>

Delete branch

git branch -d <branchName>

Clean-up local branches deleted on remote

Delete all branches that are deleted on the remote server

git fetch --prune

Submodules

The repository ("super repo") pulling the submodules can be seen as a meta repository. It only holds the commit ID's of its submodules (and possibly files that are checke into the super repo like in any other repository).

Add a git submodule

$  git submodule add --name <submodule-name> git@github.com:holzkohlengrill/submodule-repo.git <path-in-super-repo>/

path-in-super-repo and submodule-name are optional.

Get submodule contents after super repo checkout

Do this only once:

$ git submodule init

Then:

$ git submodule update

Update commit status of submodules in super repo

  1. Checkout the commit of the submodule to update (cd into the submodule folder and git checkout the commit)
  2. cd back to the super repo root folder and commit the changes (to verify look at the output of git status)

Merging

Fast-Forward

ff-no-ff

  • Left: Fast-Forward (no changes on master until merge) >> Linear result (default in git)
  • Right: No-Fast-Forward >> Merge is visible (as a commit)

Resolve merge conficts

When a merge conflict come up your file(s) will be edited by git (some markers and the conflicts will be inserted):

What you have locally

<<<<<<< HEAD:file.txt
Hello world
=======

What was introduced by the other commit

=======
Goodbye
>>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086:file.txt

Where 77976da35a11db4580b80ae27e8d65caf5208086 is the commits hash you tried to merge from.

Merge conflict workflow

  1. Fix merge conflict in stated files by git (see markers).
  2. git add <filename>
  3. git commit -m "blah, fixed merge conflict" (NO DOT at the end!)
  4. git push origin master

SSH

Cloning using ssh and private keys is also possible, you only need to add your public ssh-key cat ~.ssh/id_rsa.pub (implied that you ever run ssh-keygen otherwise id_rsa.pub does not exist) to bitbucket/github in your profile section.

SSH on Windows

  • Use git bash (no cygwin, Msys2, ... since the paths might be different)
  • ssh-keygen -t rsa -C "your_email@example.com"
  • Add key on github/bitbucket/... (show key with cat cat ~/.ssh/id_rsa.pub)

Rewriting the History

A good start is this.

Filter branch

Copy a folder (including its history) from a repository to another

See https://git.luolix.topmunity/t5/How-to-use-Git-and-GitHub/Adding-a-folder-from-one-repo-to-another/m-p/5574#M1817

For rebasing an old version of a repository underneath a new version of another repository see here

GitHub related

Issues

You can use keywords (variants) to close issues with the following keywords:

close{, s,d}
fix{, s,d}         // Leaves the issue open (only references the issue with the commit)
resolve{, s,d}

For example "Closes #35" closes issue number 35.

For further information refer to the official website

Search

  • extension:ini (no space!) will search for files having the file extention .ini
Clone this wiki locally