1

I followed the instructions from this stack overflow question to perform an interactive rebase but the interactive rebase session doesn't pull up all 8 of my previous commits (the history of the repo only has 8 commits).

This is my current commit history:

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git log --oneline
80b0645 (HEAD -> master, origin/master) Applied Bill's changes. Resolve merge conflict.
cdfcbf1 Modified line 1.
073e94b Modified line in newmodule.py
d39ae96 Added newmodule.py
118a892 deleted newmodule.txt
81c7945 Changed newmodule.txt added Hello World!
add5483 Minh added newmodule.txt
386249b First commit.

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~8
fatal: invalid upstream 'HEAD~~8'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~7
fatal: invalid upstream 'HEAD~~7'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~6
fatal: invalid upstream 'HEAD~~6'

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git rebase -i HEAD~~5

It works for HEAD~5 and this is all I see in the interactive session.

pick add5483 Minh added newmodule.txt
pick 81c7945 Changed newmodule.txt added Hello World!
pick 118a892 deleted newmodule.txt
pick d39ae96 Added newmodule.py
pick cdfcbf1 Modified line 1.
pick 073e94b Modified line in newmodule.py

# Rebase 386249b..80b0645 onto d39ae96 (6 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# ... 

I want to revert the state of my repository to what it was like immediately after the first commit (386249b) but as you can see, I don't see my most recent commit (80b0645). I tried dropping the commits:

d add5483 Minh added newmodule.txt
d 81c7945 Changed newmodule.txt added Hello World!
d 118a892 deleted newmodule.txt
d d39ae96 Added newmodule.py
d cdfcbf1 Modified line 1.
d 073e94b Modified line in newmodule.py

Which seems to have done the job (after rebasing my commit history looks like this):

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$ git log --oneline
386249b (HEAD -> master) First commit.

mtran@whg355 MINGW64 ~/Desktop/20-0082-00/src (master)
$

So I wonder:

  1. Why commit 80b0645 wasn't included in the count?
  2. Why/if rebasing is suppose to show my very first commit (386249b)?
  3. Why git rebase -i HEAD~5 worked (and what 5 refers to)?

Per suggestions to run git log --all --decorate --oneline --graph:

$ git log --all --decorate --oneline --graph
*   80b0645 (HEAD -> master, origin/master, origin/HEAD) Applied Bill's changes. Resolve merge conflict.
|\
| * 073e94b Modified line in newmodule.py
* | cdfcbf1 Modified line 1.
|/
* d39ae96 Added newmodule.py
* 118a892 deleted newmodule.txt
* 81c7945 Changed newmodule.txt added Hello World!
* add5483 Minh added newmodule.txt
* 386249b First commit.
MTV
  • 91
  • 9
  • 2
    Try `git log --all --decorate --oneline --graph`: I suspect you have a branch-and-merge, so that while there are 8 commits, there aren't 7 *previous* commits starting from the end and working backwards. (This goes along with the message you have on the topmost commit.) – torek Jul 29 '20 at 00:32
  • @MTV : the key extra option suggested by @torek is `--graph` : you will view the forks and merges in your history – LeGEC Jul 29 '20 at 10:18

2 Answers2

2

git log --oneline is very useful, but doesn't show you the merge commits.

If you add the --graph option, my guess is you will see something close to :

$ git log --oneline --graph
* 80b0645 (HEAD -> master, origin/master) Applied Bill's changes. Resolve merge conflict.
|\
| * cdfcbf1 Modified line 1.
* | 073e94b Modified line in newmodule.py
|/
* d39ae96 Added newmodule.py
* 118a892 deleted newmodule.txt
* 81c7945 Changed newmodule.txt added Hello World!
* add5483 Minh added newmodule.txt
* 386249b First commit.

To answer your question(s) :

  1. git rebase will drop merge commits, and create a linear sequence of commits ; you may try git rebase --rebase-merges (link to docs) if you have a need to preserve them

I'll answer 3. before 2. :

  1. you actually wrote HEAD~~5 (note the extra ~), which translates to "6 commits ago" (or HEAD~6)

HEAD~6 means "start from head, and follow 6 times the 'first parent' link" ;
if you look at the graph above : cdfcbf1 is "side tracked" (it is the second parent of 80b0645).

So : going up 6 commits from master takes you to your "First commit"

As for 2:

  1. git rebase -i HEAD~6 will replay commits starting from HEAD~6, HEAD~6 not included

Suppose you wanted to include commits starting from 118a892 deleted newmodule.txt :
you would write git rebase -i 81c7945 (or equivalently git rebase -i 118a892~ : the first parent of 118a892)

For the very first commit in your history, you cannot write 386249b~, because that commit does not have a parent ;
if you want to replay commits including the very first commit in history, there is a special --root option :

git rebase -i --root

[edit] to illustrate how to count the ~ :

HEAD   * 80b0645 (HEAD -> master, origin/master) Applied Bill's changes ...
       |\
       | * cdfcbf1 Modified line 1.
HEAD~  * | 073e94b Modified line in newmodule.py
       |/
HEAD~2 * d39ae96 Added newmodule.py
HEAD~3 * 118a892 deleted newmodule.txt
HEAD~4 * 81c7945 Changed newmodule.txt added Hello World!
HEAD~5 * add5483 Minh added newmodule.txt
HEAD~6 * 386249b First commit.
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • Ah, I wasn't aware that the double tilda `~~` meant something different. – MTV Jul 29 '20 at 14:27
  • Your guess about the graph was pretty much spot on. – MTV Jul 29 '20 at 14:29
  • `git rebase -i [ParentOfStartingCommit]` or the version with the tilda is a lot more straight forward than computing offset relative to HEAD. I will use that from now on. Understood your note about `--root`. – MTV Jul 29 '20 at 14:31
  • I won't be using `HEAD~n` approach but I'd still like to understand something you wrote that was a bit unclear to me: `HEAD~6 means "start from head and follow 6 times the 'first parent' link"`. Is this how I ought to count backwards? _80b0645_ --1--> _cdfcbf1_ --2--> _073e94b_ --3--> _d39ae96_ --4--> _118a892_ --5--> _81c7945_ --6--> _add5483_? This can't be right since the path I take should land me on the parent node (`386249b`, which shouldn't be included). I'm getting the feeling the problem is that people aren't disambiguating to count the _edges_ (transition) or the _nodes_ (commits) – MTV Jul 29 '20 at 14:46
  • Another way of counting, which more consistent with what you've written, is: **[1]**_80b0645_ --> **[2]**_d39ae96_ --> **[3]**_118a892_ --> **[4]**_81c7945_ --> **[5]**_add5483_ --> **[6]**_386249b_. Where the **[6]** node isn't included, as you've suggested. – MTV Jul 29 '20 at 14:47
1

1 because HEAD~~5 is precisely that revision, so it's not included.

2 it could... if you used --root.

3 because you have 8 revisions in your branch.... HEAD is always where you are standing.... then you use ~~5 which translates to 6 revisons back.

eftshift0
  • 26,375
  • 3
  • 36
  • 60