Git - Remove commit from history but lesve the code - github

I am using git on VS2019
I was wondering if there is a way to remove old commits but always keep the latest code. The reason is that when I work on a big change, I do a lot of commits after checking every small step but at the end it is annoying when I click on view history and need to search an old commit to compare the changes. I would like to remove specific commits but leave the changes. In that way I will see on history only the main milestones of the developing process. There is a way to do that??

It sounds like in these scenarios, you're developing a new feature, in which case you should be using a branch+pull request approach to development. During the pull request, you can do a squash merge. It's not all in the command line, but that might be for the best anyway.
If you're already working within a feature branch, then I like VonC's approach.

It seems that you want the git rebase feature.
If you know how many commits you want to squash together, you can use
git rebase -i HEAD~N
You can also do it in interactive mode:
git rebase --interactive HEAD~N
Be aware that if you merging commits you have already pushed, you may have trouble with your next push.
For more details, see: https://www.internalpointers.com/post/squash-commits-into-one-git

You can follow a workflow similar to "Git better with fixups " from Atul Sharma
For the commits which are incremental improvement for the same step, use git commit --fixup small step, which allows you to "do a lot of commits after checking every small step".
(You can see it in Git Extension in Visual Studio)
But at the end, you can cleanup all those small steps with git rebase --interactive --autosquash <First step commit> (assuming you have not pushed those commits yet)
That way, you end up with a cleaner history.

Related

How do I keep a fork of a branch in sync with the actual branch while also keeping the edits I made to the fork?

There is a library with a branch named dev which I created a fork of here. I then made a commit to my fork so that it would better suit my needs, and I intend to make further commits in the future. However, as the library is still in development I would also like my fork to stay up to date with the changed made in the original dev branch so that it has all of the latest bugfixes and such. Is it possible to sync the two branches while keeping my personal changes?
Edit:
I've looked at the possible duplicate and it seems like an appropriate answer but I just want to clear up one thing before I accept it - I need to sync to just the dev branch and not the whole repo, so would I do git rebase upstream/dev? What does git rebase upstream/master even do?
You'll want to periodically rebase your fork. Alternatively, you could merge the changes in if you'd like to preserve the history.

Going back in time on Github?

How do I go back to a previous build? For example going back to the July 30 state?
There are a number of ways to functionally undo a series of commits in Git. But given that the branch in question is published, and likely shared by several people, I would recommend using git revert here. git revert adds new commits on top of your current branch which undo previous commits. These revert commits can be thought of as mirror images of what was done in previous commits. Something like this should work:
git revert 00bfe1b^..a013402
This should add two commits, one to undo the Aug-9 commit and one to undo the Aug-13 commit.
As a side note, you could have also done this:
git reset --hard HEAD~2
This would have completely nuked the two commits on top of Jul-30. However, this involves rewriting the history of the branch, which isn't desirable if other people may already be sharing this branch with you. In this case, just play it safe and use git revert.
To view (browse the file tree) the repository state at a certain commit given at least the first four characters of commit's hash, the following URL schema for GitHub can be used (at the time of writing):
https://github.com/{username}/{repository name}/tree/{hash}
If you want to hard reset your GitHub repository to a specific commit, do a git reset --hard {hash} in your local (stored on your computer) repository then force push it to a remote repository (like GitHub) via git push --force.
Of course, hard resets are dangerous. You can git revert or git reset and stash unstaged changes, and I'm sure there are other ways to achieve similar effects.

Amend merged pull request

I made a pull request which was merged to a project. It so happens that the code needs a minor modification. How can I possibly change this with no access to the master project whatsoever? Am I out of luck and I have to do a new PR?
Thanks.
Yes, you should submit another pull request.
When using any of Git's "rewriting" commands like commit --amend or rebase it is important that you avoid changing shared commits.
In its Rebasing chapter, the Git Book says:
The Perils of Rebasing
Ahh, but the bliss of rebasing isn’t without its drawbacks, which can be summed up in a single line:
Do not rebase commits that exist outside your repository.
If you follow that guideline, you’ll be fine. If you don’t, people will hate you, and you’ll be scorned by friends and family.
When you rebase stuff, you’re abandoning existing commits and creating new ones that are similar but different. If you push commits somewhere and others pull them down and base work on them, and then you rewrite those commits with git rebase and push them up again, your collaborators will have to re-merge their work and things will get messy when you try to pull their work back into yours.

Deleting a merge from History Git

I'm trying to figure out how to fix a merge problem me and my team are facing. I'm working on this project at school, and my team has made a lot of progress, but one of the team members who didn't know what he was doing force merges his code into the master branch. His branch is like 2 days old and we've already implemented a lot of new functionality since time, his branch is probably 20 or so commits away from head. I've tried rolling back to a stable master branch but his branch is intermingled with the stable so I can't seem to retrieve the stable back. Any suggestions? we are fairly new to git, but that person had no idea what was going on and just force merged his code without resolving the commits.
Go and sit on his computer.
Type git reflog, it will show you the full commit history (as well as other things). Find out the last good commit id , check it out git checkout SHA-1. create branch at this point and commit it back again. Once you are on the right commit your repository will "get back" to the last good place.
Another option is to perform a git bisect and to find out what is the bad commit.
Click here for blog about reflog
Click here for blog about bisect
Good luck.

How should I manage "reverting" a branch done with bookmarks in mercurial?

I have an open source project on bitbucket. Recently, I've been working on an experimental branch which I (for whatever reason) didn't make an actual branch for. Instead what I did was use bookmarks.
So I made two bookmarks at the same revision
test --the new code I worked on that should now be abandoned(due to an experiment failure)
main -- the stable old code that works
I worked in test. I also pushed from test to my server, which ended up switching the tip tag to the new unstable code, when I really would've rather it stayed at main. I "switched" back to the main bookmark by doing a hg update main and then committing an insignificant change. So, I pushed this with hg push -f and now my source control is "correct" on the server.
I know that there should be a cleaner way to "switch" branches. What should I do in the future for this kind of operation?
tip is not a widely useful concept in a repository which has branches of any kind. Whether you are using bookmarks, named branches, or anonymous branches, tip always means the most recent commit on any branch, which is rarely something you care about. The real solution to your problem is to stop worrying about the tip!
I don't really understand your question, since you are switching (without quotes) branches, even if they are not named branches, they are still branches when you use bookmarks.
The mistake you had was an honest mistake and I see no way of having Mercurial protect you from doing that again with bookmarks (marking the same rev with different bookmarks and committing with the wrong one). What I can tell you though is how to do private local branching with Mercurial, and this way you can avoid having the consequences you just had:
You use named branches and phases
Mercurial Phases are really sweet, let me explain them real quick. You can mark revisions to three special states called phases, and these are: secret, draft and public.
secret: Don't get pushed. Can be modified through history editing.
draft: Get pushed. Can be modified through history editing. This is the default state of any revision.
public: Get pushed. Will issue a warning when using history editting extensions on them (strip, rebase, histedit,...).
As mentioned, all local revisions are draft by default, when you push them, they become public. You can use the hg phase command to mark revisions to a particular phase, but if you are going from #3 to #2, or from #2 to #1 (according to the previous numbering), you need the -f argument to force the change, this is:
secret --> draft --> public
To go to the left you need to use --force or -f.
Here is what you do:
hg branch experiment
hg commit -m "Opening experimental branch" //say this creates revision 123
hg phase -sf tip //s is for secret, f is for force
//... hack hack hack
hg commit -m "Uh oh screwed up here"
hg push //no secret revisions are pushed
Now, you can just abandon that branch and leave it like so, it wont ever get pushed. Forget about it and even just close it so that it wont bother you when you list your branches. It won't get pushed it won't get listed, so just don't worry about it.
However, if you have OCD, just strip (hg strip) the branch at the commit where the branch was opened, and it is gone:
hg strip 123
If you have an already existing branch, you can phase several revisions at once like this:
hg phase <start revision>::<end revision> -sf
To make your secret branch draft or public, just phase the latest revision to those phases:
hg phase -d tip //assuming you are in the experiment branch
Then push, and the branch will become public.
Mercurial has been increasingly becoming better at history modification without changing it's general philosophy of discouraging just that. Phases are meant to protect you from accidental history modification as well as from sharing what you don't mean to.
How *I* use bookmarks
Personally, I use bookmarks for debugging and for when I want to try 2 different ways of doing one thing. To me, bookmarks are useful when you want to do anonymous branches (update to a previous revision, commit and fork the history) but want to keep things intelligible.