git undo effects of pushed commit on repository size - garbage-collection

The question of undoing a previous push to a remote repository has been asked several times, but it seems to me that the answers are incomplete. Following the suggestions in Git - Undo pushed commits, I am able to reset a remote repository so that its behavior is as if the last commit never happened. However, it seems that the effects of the undone commit still show up in the size of the git repository.
Here's the hypothetical situation:
A user does git add, git commit that puts a huge file, "BigFatFile.bin" into version control. He pushes the changes to the remote repository. Let's suppose that this file is HUGE, maybe 1 GB. We don't want to maintain such files in git. So we try to undo this bad commit as follows:
Clone the remote repository.
Do git reset --hard HEAD^ to remove the last commit.
Do git push -f to push changes to the remote repository.
This seems to work, except for the fact that the effects of the push are still visible in the size of the remote repository. Its size has grown by 1 GB.
It is possible on the local copy of the repository to do cleanup steps, using git reflog and git gc and git repack, which reduces the size of the local repository to what it was before the commit of "BigFatFile.bin". But doing a git push (or git push -f) doesn't seem to reduce the size of the remote repository.
How can I permanently undo the last pushed commit so that the size of the repository returns to what it was before the push?

The size of the remote repo shouldn't matter to the clients who are cloning it: the cloned repo should be small again.
As I mentioned in "Clean up large files on git server", you would need to perform the git gc; git repack -Ad; git prune on the server side, in order to ensure the size of the repo there shrinks.
Depending on the server, that might not be possible. For instance, if that was a GitHub-hosted repo, you would need to contact the GitHub support in order to ensure that cleanup task is performed.

Related

problem with my git repo, I lost all my commits?

I was trying to upload a file via terminal.I am trying to learn git.
**
git add /Users/serra/Documents/useSDWebImage
git commit -m "learning on process"
git remote add origin
git push -u origin master
**
then I got this message error: failed to push some refs to ....
I tried those commands then I have only the file I want to upload
to repository I have lost rest of the repository.What should I do?
**
git pull --rebase origin main
git push origin main
git pull origin master
git push origin master
git push origin master --force
**
TL;DR
You need to find a backup, somewhere, of origin/master.
git reflog might help you.
The error
First, let's go over your first four commands and explain what the mistake was.
In the first two commands, a git add and git commit, you are creating a commit in your local sandbox, building on whatever was in your sandbox beforehand.
In the third command, you add your remote, which means that your commit was not made on top of that remote, but on top of something else.
In your fourth command, Git correctly tells you that you cannot push, because your local sandbox is not built on top of the remote. It's important to pay attention to Git's error messages, they're almost always informative.
Now, you're not showing outputs from any of the commands you ran, but I'm guessing git push origin master --force is what deleted stuff on your remote.
What you should have done
Normally, you clone the remote first, then commit stuff on top of it:
git clone <URL>
cd <SANDBOX_DIR>
git add <file inside this directory>
git commit
git push
How to fix this
There are several ways, but they're all based on recovering stuff from a backup that hopefully exists somewhere.
If your remote is GitHub, it keeps a history of references, you should be able to find that old master branch somehow there. If your remote is some other server, that is hopefully true too. If another team member has a sandbox that had the valid master you want to restore, they can fix things by doing a git push origin master --force in their own sandbox, but make sure they understand what they're doing before they do it.
My answer here is not complete, because you didn't provide enough information. I will update it if you update your question with more details about your remote.
Update - git reflog might help
When you did git pull origin master, assuming master is the branch you care about, you probably got a local copy of the correct master commit you want on origin. You can use git reflog to see the history of your local HEAD in your sandbox. If you find the good commit there, this solution could work:
Here I'm assuming these is not work you want to preserve in your sandbox.
git checkout master
git reset --hard <good commit> # WARNING: destroys any uncommitted local changes
At this point, check that your sandbox contains the files you want to restore to origin. If so, proceed with this command:
git push --force origin master
But be warned, this will overwrite what's on origin. It's only appropriate if you have carefully validated that master in your sandbox really contains the history you want to restore on origin.

How to copy commits from one Git repo to another?

Last week I created a Github repo and forgot to select a license for the repo. Now there are already 3 large commits.
I have asked the 3 contributors if it is ok if I delete the repo and then create it again with the same name and this time selecting the license when creating the repo, and they were fine with that.
Question
Is there a way I can get the commits into the new repo (this time the first commit is the LICENSE file) and still keep the commit meta info?
Is there a way I have get the commits into new repo (this time the first commit is the LICENSE file) and still keep the commit meta info?
Yes, by adding a remote and cherry-picking the commits on top of your first commit.
# add the old repo as a remote repository
git remote add oldrepo https://github.com/path/to/oldrepo
# get the old repo commits
git remote update
# examine the whole tree
git log --all --oneline --graph --decorate
# copy (cherry-pick) the commits from the old repo into your new local one
git cherry-pick sha-of-commit-one
git cherry-pick sha-of-commit-two
git cherry-pick sha-of-commit-three
# check your local repo is correct
git log
# send your new tree (repo state) to github
git push origin master
# remove the now-unneeded reference to oldrepo
git remote remove oldrepo
The rest of this answer is if you still want to add the LICENSE to your previous repo.
Yes. You can place your LICENSE commit as the first commit by rebasing.
Rebasing is gits way of rearranging commit order while keeping all the commit authors and commit dates intact.
When working on a shared repo, it's generally discouraged unless your entire team is git-fluent. For those that aren't, they can just clone a fresh copy of the repository.
Here's how you get your LICENSE commit as the first commit.
1. Update and rebase your local copy
Check out your project and place the LICENSE file in a commit ON TOP of your current 3 commit stack.
#create LICENSE file, edit, add content, save
git add LICENSE
git commit -m 'Initial commit'
Then do an interactive rebase on the master branch to REARRANGE the commits.
git rebase -i --root
It will open an editor. Move the bottom line (your "Initial commit" commit, the most recent commit) to the top of the file. Then save and quit the editor.
As soon as you exit the editor, git will write the commits in the order you just specified.
You now have your local copy of the repository updated. do:
git log
to verify.
2. Force push your new repo state to github
Now that your copy is updated, you have to force push it to github.
git push -f origin master
This will tell github to move the master branch to its new location.
You should only force push in rare occasions like this where everybody working with it is aware of the pending change, else it will confuse your collaborators.
3. Synchronize collaborators to github
Lastly, all the collaborators will have to synchronize to this repository.
First they must have clean repositories as the following command can be destructive if there are unsaved changes.
# make sure there are no unsaved changes
git status
# pull the latest version from github
git fetch
# move their master branch pointer to the one you published to github.
git reset --hard origin/master
That's it. Everybody should be in sync now.
I had a similar problem where I forgot to fork a repo to my github and added several commits before I realized my mistake.
I found a pretty simple solution.
First remove the remote to the original repo
git remote remove origin
Second add a remote to the new fork on my github
git remote add origin <my repo URL>
Then I pushed to origin master and all of my commits showed up on my github.
I used the following approach:
Clone the source repo to a folder like /c/SrcRepo
Clone the destination repo to a folder like /c/DstRepo and switch to the destination branch
In the root folder of the destination repo run the command:
git pull /c/SrcRepo srcBranch --allow-unrelated-histories
No necessary to create an additional remote reference
Based on #Moocowmoo's answer but trying to streamline it bit more
What this does differently is tries to avoid conflicts as much as possible, just assuming that the remote is correct.
It doesn't however handle deleted files well, so there is still a manual element.
# assuming you are already on the branch you want to be
git remote add oldrepo https://github.com/path/to/oldrepo
git fetch oldrepo
# take all or subset of changes from a branch
git cherry-pick --strategy recursive --strategy-option theirs oldestCommitHash^..latestCommitHash
# or take all changes included in a specific merge commit (easiest)
git cherry-pick --strategy recursive --strategy-option theirs mergeCommitHash^..mergeCommitHash
# handling deleted files/unhandled conflicts
# just keep repeating this section
git mergetool
# either c/m or d based on if you want to keep or delete the files
git cherry-pick --continue
Destination Git = UrlD (existing content doesn't matter)
SourceGit = UrlS
git clone UrlS
git remote add origin2 UrlD
git push -f origin2 master
Now the Destination will have the same data as Source(You can also use origin instead of origin2)
you can try this, it's easy and straightforward. This will push all commits before (and including) the hash you use as <last-commit-hash-from-old-repo> to the other repo:
git clone https://github.com/path/to/new-repo.git new-repo
cd new-repo
git remote add old https://github.com/path/to/old-repo.git
git remote update
git merge --allow-unrelated-histories <last-commit-hash-from-old-repo>
git push origin main
if anyone needs to push all commits from a repo to another as a single commit (like I needed), you can simply add --squash to the merge command like this:
git clone https://github.com/path/to/new-repo.git new-repo
cd new-repo
git remote add old https://github.com/path/to/old-repo.git
git remote update
git merge --squash --allow-unrelated-histories <last-commit-hash-from-old-repo>
git push origin main
In my case I needed to find out differences between the old and new repos. So in the new repo added the old one.
git remote add old https://gitlab.site.az/old-blog.git
Fetch all remotes
git fetch --all
Find different commits
git log --graph --oneline --pretty=format:"%h%x09%an%x09%ad%x09%s" --abbrev-commit --date=relative develop..old/develop
Get commits you selected
git cherry-pick SHA1 SHA2 SHA4

After GIT commit, I did GIT push but the message said everything up-to-date

I'm new to Git. We're in Linux, and I just inherited someone's project family.
I recently did:
git add Bom.xml Bom.csv N.cpp makefile ../mm
git commit -a
(said On branch Bom, your branch is ahead of master by 2 commits. use git push to publish your local commits. Untracked files: list of things I don't want to commit anyway). Nothing added to commit but untracked files present.
then
git push
But it said everything up-to-date. I'm not sure where to look to see that my content is pushed up to my branch on the server. I know I had file changes since my last commit. It's a tough thing to search for the answer online. I looked at up-to-date too, and added the git add and the -a to my commit, but it still says up-to-date when I try to push.
Thanks!
Mich
Like the link you mentioned, make sure you have added the file you want to commit into the staging area. Each time you want to commit
run git status to check.
And then run git add file to add file to staging area.
Run git status to check whether the file is added to the stage.
Then run git commit -m "some message" to commit
run git log to check your commit history check whether you have committed successfully
then check your remote branch by running git branch -a
if your remote branch doesn't have your local branch branch-name
then run git push origin branch-name to push your local branch to remote.

How to handle this merge issue in GIT

I am having a situation here. I did some commit to master branch and after move these commit to
other branch x using and
git cherry-pick
and I run git cherry-pick on x branch itself. Now after this git cherry-pick, forgot to run git push command.
Almost at same time my colleague did the git cherry-pick for his commits and did the git push.
When I see the git log on his machine I couldn't find my commit and realize that I forgot to run git push.
I went to my machine, did the git push. But I am seeing this message now
Without a better log output it is hard to tell, what happend.
I guess you both had the same base commit, each of you did a cherry-pick, and you merged both cherry-picks in order to be able to push it.
The log above shows one commit from you (cf5b726), one commit from your colleague (1aa2ecd) and a merge (28529d0) of the first two commits, which seems to originate from a git pull.
And yes, the merge carries the changes of both merged commits. - After all that's exactly the point of a merge. ;)
You can use git log --graph or git log --format=raw (or magit for Emacs) to see the parents of a commit.

git says Everything up-to-date

First of all, I am a noob at using git.
I was working on a project and did a commit and pushed to remote github repository.
But, then later I realized that I did some mistake, so I did $git --amend -am "My message"
Now, I was not able to push again to the remote server as I was getting error. So, I thought of deleting the remote github repo & recreated the same with the same name.
Now, when I try to push, it says "Everything up-to-date".
Please guide as to how do I solve this?
Sounds like two things have gone wrong, here.
First up, you amended a commit that had become part of the remote repository's history, which is a bit of a no-no. Rather than re-answer this gripe, I'll direct you to the answer: How do I push amended commit to the remote Git repository?
Next, chances are that even though you re-created the remote repository, your local repository still has the local history from the old one. what you'll want to do is run git remote rm origin, then git gc, then git remote add origin <path_to_repo>, then finally git fetch origin. This should pick up the new remote repository, and allow you to push your changes to it.

Resources