Advanced Git
Tags: github, git
Published: 2022-10-13 16:34:04

Besides some of the basic commands in git, there is a whole host of other commands. And strategies to master to get the most out of your project and reduce the amount of time maintaining codebase.

## Proper Commit Messages

The summary or first line of the commit can be up to 50 characters

which forces developers to think about what will be in this commit and for quick reading when looking at the summaries (such as when you use `git shortlog`).

The details or third line going forward, of the commit, can be 72 characters per line.

 - Because git adds two blank spaces on either side of the details, centring it in the terminal when you use `git log`.

The commit message should explain what is going into this commit and why you are making the change. If you cannot explain it, then maybe it is time to pause and reflect on this commit.

- There are exceptions to the rules, though. If the change is noticeable, then, of course, you can do it on one line, as long it is less than 50 characters. If you cannot do so, then you will need to add in more detail in the body.

- Here is your chance to also explain if this commit will have any side effects

- How it will fix the issues

- Try adding links to commits if you found the answer on stack overflow.

- This help will help developers, and reviews of your pull request in knowing what you have done and what reason for this commit without having to look into the code and only to guess the reason.

- DO NOT bunch changes into one commit if you need to use “and” then that should be an induction you should split the commit up and put them into their commits.

Use present tense person will make it easier to read the commit.

## Some Git Commands I Use

### Add — patch

Before we begin with rebasing, let’s talk a little about `add — patch`, which allows you to add part of the code into staging while leaving the rest to be commit later.

Suppose you make lots of changes to one file but forgot to commit instead of committing the whole thing and explain what is going on.

To start by typing, `git add — patch LocationOfFile` this will start up the patch screen and give you options to split add some of the changes

```
    Stage this hunk [y,n,q,a,d,/,e,?]?
```

By typing in `?` for help, the following will display

```
    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
```

Some of those will only appear at specific types of hunks. Here are some of the most used sections:

 - y / Yes will stage that hunk
 - n / No will not stage that hunk
 - q / quit stops `add — patch` any remaining hunks will not be added
 - s / smaller will shrink the hunk into smaller pieces. However, this will only use in big hunks
 - e / edit remove the code that will not be stage from your text editor for that hunk

### Rebase

Reapplies commits on top of the base. For example, when you are on a branch and type in `git rebase develop`, it will take the first commit, on this branch, and change the SHA to the SHA of the last commit, HEAD, on the develop.

Which updates the SHA for each of the commits, in that branch, if you previously push your changes up to the remote repo, then you will have to to `git push -f origin branchName`. A word of warning, if the branch is shared, you will need to tell everyone that is using it to pull down the branch to avoid duplicating code or better DO NOT rebase on a shared. Furthermore, because the SHA changes, you must NEVER rebase on develop or master branch as everyone on the team will have a separate version of the project and cause unforeseen issues with commits later on.

Any example of rebasing is this:

_Before Rebase_

```
    A — -B — -C topic

    /

    D — -E — -F — -G develop
```

_After `git rebase develop`_

```
    A’ — B’ — C’ topic

    /

    D — -E — -F — -G develop
```

Now why you want to do this, well, because this will keep your git history clean without having multiple merges commits. Those merge branches which serve no purpose other than showing when the developer merges their branch with develop or master branch by having a clean log you to view all of the commits a glance.

So if you look at this:

```
    ec1c2a9 Topic #6

    033c6bd Merge branch ‘develop’ into topic

    82a5ad2 Topic #5

    82a5ad2 Topic #4

    9953bb1 Topic #3

    a12s7zk Merge branch ‘develop’ into topic

    161e1aa Topic #2

    9sdb12r Merge branch ‘develop’ into topic

    a397dbe Topic #1
```

or this

```
    ec1c2a9 Topic #6

    82a5ad2 Topic #5

    82a5ad2 Topic #4

    9953bb1 Topic #3

    161e1aa Topic #2

    a397dbe Topic #1
```

### Pull — rebase — preserve-merges

Now, if we look at git pull, by default it does a merge instead of a rebase, this could result in the git history containing, merge commits, which undermine the result we want with rebase. By changing the default to ‘pull rebase’, you will not need to remember to do this when you do a pull.

```
    git config — global pull.rebase preserve
```

Now, remember when I said never rebase develop or master well. There is an exception to the rule if you add in — preserve-merges this or rebase = preserve in the Git config than pull — rebase will not try to remove the merge commits that might be on the develop or master branch. Thus leaving existing commits alone and you will not have to force push to the remote repo since all it will do is pull down the commits and move the commits in front of whichever branch you are pulling down too.

### Rebase (-i) — interactive

Rebase interactive or Rebase -i, for now on, is the most potent way of multiple git history, why would you want to do such a thing well. Let us say you have a working branch that you may make commits that are not in order or do a bunch of commits that are all part of the same items. Or you decided to hack away at a problem until you found a solution leaving behind a bunch of commits that no longer apply. Suppose you submit a pull request like this. It will take a well to figure out what the actual changes. Also, you end up with a measly history where it becomes impossible to find what difference and a reason behind it.

So along comes `rebase -i` where you can squash, fixup, reword, drop, editing and reorder commits — turning the commits into groups of logical progression. Before I start with the main sections, there is one other thing you can do in `rebase -i` called exec, where you can execute SHELL commands during your rebasing. Most of the time, you will not need to use it, but it is there if you need it.

To start you will need to type `git rebase -i` then choose either name of the branch to base off of usually develop or master, but it can be any local branch, or you can use a commit’s SHA which will be after the commit you want to use edit, for example,

```
    git rebase -i a397dbe

    82a5ad2 Topic #4

    9953bb1 Topic #3

    161e1aa Topic #2

    a397dbe Topic #1
```

It goes from the latest, the top, to oldest, the bottom, so If you want Topic #2 to start your rebase, then you will get the SHA of Topic #1 as that is base commit to starting.

Once you do this, an editor that you configure or vi by default will open up, and give you the options, by default pick is select meaning that you have chosen that commit to stay.

```
    pick 835f50c Topic #2

    pick 0d5bf2f Topic #3

    pick 90e56ea Topic #4

    pick 25e1b8c Topic #5

    pick cec1509 Topic #6

    pick f7e230e Topic #7

    pick 2de656d Topic #8

    pick 31bc4a1 Topic #9

    pick 7565ef6 Topic #10

    pick c6d5e23 Topic #11

    # Rebase 713274d..c6d5e23 onto 713274d (10 command(s))

    #

    # Commands:

    # p, pick = use commit

    # r, reword = use commit, but edit the commit message

    # e, edit = use commit, but stop for amending

    # s, squash = use commit, but meld into previous commit

    # f, fixup = like “squash”, but discard this commit’s log message

    # x, exec = run command (the rest of the line) using shell

    # d, drop = remove commit

    #

    # These lines can be re-ordered; they are executed from top to bottom.

    #

    # If you remove a line here THAT COMMIT WILL BE LOST.

    #

    # However, if you remove everything, the rebase will be aborted.

    #

    # Note that empty commits are commented out
```

_Squash_

Squash is the ability to merge two commits while preserving the commit messages, which allows you to view which commit messages and reword them into a new combine commit.

```
    pick 90e56ea Topic #4

    squash 25e1b8c Topic #5
```

In the example above, Topic #5 will be merged into Topic #4 then open up your text editor.

```
    # This is a combination of 2 commits.

    # The first commit’s message is:

    Topic #4

    # This is the 2nd commit message:

    Topic #5
```

Here you can decide what the new commit message will be or leave as is, and the combined messages of Topic #4 and 5 will use.

_Fixup_

Similar to squash but instead of the entering in a commit message. The message is from the commit being merge into, will be used.

```
    pick 25e1b8c Topic #5

    fixup cec1509 Topic #6

    fixup f7e230e Topic #7
```

In this example, Topic #6 and 7 will merge into Topic #5 and use that message.

_Reword_

Allows you to fix misworded or misspelled commits, this gives you a second chance to set a commit wording to make it more clear.

_Drop_

Will remove commits from git history by either stating it on the line or by deleting the line. A huge word of warning if you remove a commit, any subsequential changes. To the same line of code. That was made by later commits will also be affected. Because it has never happened, in the git history, thus any change that invades that will also change and possibly be remove the code from history going forward.

_Editing_

It takes `commit — amend` to the extreme where you can amend commits in the middle of two commits instead of at the end. It allows you to split commits up or remove a piece of code that was mistakenly left behind.

To start editing, choose a line in the `rebase -i` option, save and exit the options. Git will start to rebase until it reaches that line where it will look like this:

```
    Stopped at 0d5bf2f05e90219eb11e2e5e91d8f6ad0c4518af… Topic #3

    You can amend the commit now, with

    git commit — amend

    Once you are satisfied with your changes, run

    git rebase — continue
```

Here you can amend the commit or make new commits then continue with the rebase.

_Reordering_

It allows you to group commits to have a logical grouping. So suppose you create a page and commit it. Then you make some other commits, then, later on, you added more to that page and commit them. However, those changes you want to keep then separate, form the create a commit. So in `rebase -i` you can cut the line with the changes and paste it under the create commit. That allows anyone looking at pull requests to see the logical progression of the page. But be warned, misusing this could result in the illogical placement of code, such as a function called, while the function itself, not created yet.

### Reflog

Now you must be wondering what if you screw up and now your branch is unusable, or your code is lost. No worries there is Reflog, which will list most of the git commands you have done for a given time, default 90 days. It makes it possible to use git rebase without worry.

It gives you a chance to reverse any git commands that have gone wrong, for instance, if a rebase has broken your application.

You can do this:

1. `git reflog` to list all of the git commands for the rebase

```
    38b323f HEAD@{0}: rebase -i (finish): returning to refs/heads/feature/add_git_reflog

    38b323f HEAD@{1}: rebase -i (pick): Clarify inc/dec operators

    4fff859 HEAD@{2}: rebase -i (pick): Update java.html.markdown

    34ed963 HEAD@{3}: rebase -i (pick): [yaml/en] Add more resources (#1666)

    ed8ddf2 HEAD@{4}: rebase -i (pick): start spanish translation (#1748)

    2e6c386 HEAD@{5}: rebase -i (start): checkout 02fb96d
```

2. Select where to reset to, in our case its `2e6c386`, or `HEAD@{5}`

3. `git reset — hard HEAD@{5}` this will reset your repo to that head

4. You can start the rebase again or leave it alone.

## Merge Conflicts

Of course, there will be times where merge conflicts will happen. First, any tools you use for merge conflicts will still work with rebase. Keep in mind, of how time works. If you make changes to a commit, that will also have changes later on. You should not make those changes unless they commit states otherwise. Or you will need to apply those changes every time the file has changed in a commit.

There are also three options you can do:

 1. `rebase — continue`, which will continue on the rebase. However, if there is a merge conflict, and it’s not resolved, you will not be able to continue until the conflict is gone.

 2. `rebase — skip`, which will skip the merge conflict; Besides, doing so may cause further issues with other commits. It is best to fix those conflicts now.

 3. `rebase — abort` which will stop the rebase and undo any changes done by this rebase. That allows you to make smaller rebase changes or rethink what to change.

## Refer:

From [https://git-scm.com/book/ch5-2.html](https://git-scm.com/book/ch5-2.html)
- Short (50 chars or less) summary of changes
- More detailed explanatory text, if necessary. Wrap it to
- about 72 characters or so. In some contexts, the first
- line is treated as the subject of an email and the rest of
- the text as the body. The blank line separating the
- summary from the body is critical (unless you omit the body
- entirely); tools like rebase can get confused if you run
- the two together.
- Further paragraphs come after blank lines.
    - Bullet points are okay, too
    - Typically a hyphen or asterisk is used for the bullet,
- preceded by a single space, with blank lines in
- between, but conventions vary here

[https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c#.d3huuguud](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c#.d3huuguud)