Reputation: 119
Hi guys I'm new to github. I just started working on a private repository with a few friends for a group project. I had to make a bunch of commits to organize code, add folders, move stuff around etc. However, this caused a clutter of commits. I want to combine all of the commits within the brackets in the photo into one commit so it doesn't looked cluttered:
I made a previous thread where I used git rebase -i HEAD~20
, and this text file pops up, however when I change everything within the brackets I drew from pick
to 'squash
I get an error: error: cannot 'squash' without a previous commit
.
Any help is greatly appreciated. Also this is my first time using github so I don't know much about it.
Upvotes: 0
Views: 147
Reputation: 72216
The first commit you want to squash is 4eb500d
.
Github doesn't show it but the commit message ("Merged and organized...") tells why this commit cannot be squashed: it is a merge commit.
Squashing means the changes introduced by the squashed commit are combined into the parent commit. But a merge commit is not a regular commit; it has two or more parent commits.
It's not clear for git rebase
into what parent to squash the commit you tell it to squash. Even more, if you squash it into one of its parents you remove the merge operation. And these are probably good reasons for Git to not allow squashing a merge commit.
Use a graphical Git client to see how the commits are related one to another and edit each branch separately. Then you can recreate the merge commits and eventually discard the current commits you don't want to keep.
Upvotes: 0
Reputation: 164769
The problem is git rebase -i HEAD~20
is showing you a false, linear history of your project. Git and Github have a bad habit of doing this and it's the source of much confusion. In reality, Git is a graph (in the computer science sense).
Here is the fake, linear history produced by git log --decorate --oneline
and unfortunately used by Github.
1ff521a (HEAD -> master, origin/master, origin/HEAD) Revert "Boulder code + minor changes"
85cb9fa Merge remote-tracking branch 'origin/master'
47d93ec Boulder code + minor changes
e6bb627 Recommit actor and sw
c6a48cc Add files via upload
1f005ec Create readme.txt
33f251b Added missing files, reuploading project
0b520fd Boulder code + minor changes
4068bca Recommit actor and sw
9b2aa1c Add files via upload
f7ed4ad Create readme.txt
14a6d35 Add files via upload
244e6d9 Create readme.txt
ce33d87 Add files via upload
86ae9a2 Add files via upload
8bec858 Add files via upload
f001fb0 Create readme.txt
d8dbf27 Create readme.txt
9ef59fc Delete Debug
64bfb3e Create Debug
aab055b Created DiggerMan folder (organization)
deb834b Added Debug Items
f219ae5 Create readme.txt
9da61f0 Added missing files, reuploading project
d6459cb added missing dll files, no other major change
42b500d Merged and organized code from last commit.
0a87678 Merge remote-tracking branch 'origin/master'
81f93fb Created new base class for objects that can be picked up
67e6369 HUD now displayed and partially implemented
4da4bff DiggerMan can now dig!
Here is the reality from git log --graph --decorate --oneline
. It shows the true relationship of the commits.
* 1ff521a (HEAD -> master, origin/master, origin/HEAD) Revert "Boulder code + minor changes"
* 85cb9fa Merge remote-tracking branch 'origin/master'
|\
| * 0b520fd Boulder code + minor changes
| * 4068bca Recommit actor and sw
| * 9b2aa1c Add files via upload
| * f7ed4ad Create readme.txt
| * 14a6d35 Add files via upload
| * 244e6d9 Create readme.txt
| * ce33d87 Add files via upload
| * 86ae9a2 Add files via upload
| * 8bec858 Add files via upload
| * f001fb0 Create readme.txt
| * d8dbf27 Create readme.txt
| * 9ef59fc Delete Debug
| * 64bfb3e Create Debug
| * aab055b Created DiggerMan folder (organization)
| * deb834b Added Debug Items
| * f219ae5 Create readme.txt
| * 9da61f0 Added missing files, reuploading project
* | 47d93ec Boulder code + minor changes
* | e6bb627 Recommit actor and sw
* | c6a48cc Add files via upload
* | 1f005ec Create readme.txt
* | 33f251b Added missing files, reuploading project
|/
* d6459cb added missing dll files, no other major change
* 42b500d Merged and organized code from last commit.
* 0a87678 Merge remote-tracking branch 'origin/master'
|\
| * 67e6369 HUD now displayed and partially implemented
* | 81f93fb Created new base class for objects that can be picked up
|/
* 4da4bff DiggerMan can now dig!
Those things that look like branches are branches. Git branches are just labels on a commit. When you git branch -d
you're just deleting the label. The actual branches are preserved after a merge. This is called the "topological order" and it's necessary to understanding what's going on in Git. The topological order is what matters.
git rebase -i HEAD~20
showed you a false, linear history making it look like you could squash all the commits together. Instead, you'll have to look at the topography and squash each branch separately.
If this seems overly complicated, it is. There's a simpler way.
The simplest is this: don't worry about having too many commits. In general, having too many small commits is better than having too few large commits. One of the purposes of version control, in particular commit messages, is to know why a change was made. Small commits make it easier to associate a change with the reason. Merging commits together merges all the reasons together. There's a lot of advice out there about squash merges, don't do it.
The number of commits and their size is not a meaningful measure. Instead, a good commit makes the code easier to understand and review for the future. For example, a commit that just fixes a typo in the immediately preceding commit is not meaningful, like Create Debug
followed by Delete Debug
. Get rid of it using fixup
or delete both commits entirely, or immediately rewrite the previous commit with git commit --amend
. Similarly, you have "Create readme.txt" four times which is probably a mistake. OTOH Created DiggerMan folder (organization)
is probably a meaningful commit, keep it.
Finally, clean up your branches before merging them. This avoids the sort of problem right now. Before merging, git rebase -i master
would select only the commits in the current branch and there wouldn't be any topological problems. It's also a good habit to get into when you work on a collaborative project and your branches need to be reviewed; you'll want to clean up your branch before submitting it for review.
Upvotes: 1