Asked  7 Months ago    Answers:  5   Viewed   34 times

I have a remote Git server, here is the scenario which I want to perform:

  • For each bug/feature I create a different Git branch

  • I keep on committing my code in that Git branch with un-official Git messages

  • In top repository we have to do one commit for one bug with official Git message

So how can I merge my branch to remote branch so that they get just one commit for all my check-ins (I even want to provide commit message for this)?

 Answers

67

Say your bug fix branch is called bugfix and you want to merge it into master:

git checkout master
git merge --squash bugfix
git commit

This will take all the commits from the bugfix branch, squash them into 1 commit, and merge it with your master branch.


Explanation:

git checkout master

Switches to your master branch.

git merge --squash bugfix

Takes all commits from the bugfix branch and groups it for a 1 commit with your current branch.
(no merge commit appears; you could resolve conflicts manually before following commit)

git commit

Creates a single commit from the merged changes.

Omitting the -m parameter lets you modify a draft commit message containing every message from your squashed commits before finalizing your commit.

Tuesday, June 1, 2021
 
AlterPHP
answered 7 Months ago
76

It seems like you want the files ignored but they have already been commited. .gitignore has no effect on files that are already in the repo so they need to be removed with git rm --cached. The --cached will prevent it from having any effect on your working copy and it will just mark as removed the next time you commit. After the files are removed from the repo then the .gitignore will prevent them from being added again.

But you have another problem with your .gitignore, you are excessively using wildcards and its causing it to match less than you expect it to. Instead lets change the .gitignore and try this.

.bundle
.DS_Store
db/*.sqlite3
log/*.log
tmp/
public/system/images/
public/system/avatars/
Sunday, June 6, 2021
 
Novalirium
answered 7 Months ago
32

So based on what you said, these files are libraries/documentation you don't want to delete but also don't want to push to github. Let say you have your project in folder your_project and a doc directory: your_project/doc.

  1. Remove it from the project directory (without actually deleting it): git rm --cached doc/*
  2. If you don't already have a .gitignore, you can make one right inside of your project folder: project/.gitignore.
  3. Put doc/* in the .gitignore
  4. Stage the file to commit: git add project/.gitignore
  5. Commit: git commit -m "message".
  6. Push your change to github.
Friday, September 3, 2021
 
Iber
answered 3 Months ago
22

You can't get there from here (as the fellow giving directions said). More precisely, it does not make sense.

The problem is that git merge --squash does not actually do a merge. Suppose your branch history looks like this, for instance (with branches topic and devel):

          H ⬅ I ⬅ J     <-- topic
        ⬋
⬅ F ⬅ G
        ⬉
          K ⬅ L         <-- devel

If you check out devel and merge topic you get a new merge commit M that contains the result of the merge, and M has two parents:

          H ⬅ I ⬅ J     <-- topic
        ⬋         ⬆
⬅ F ⬅ G           ⬆
        ⬉         ⬆
          K ⬅ L ⬅ M     <-- devel

But if you use git merge --squash topic you get, instead, a new commit (let's label it S for squash):

          H ⬅ I ⬅ J     <-- topic
        ⬋
⬅ F ⬅ G
        ⬉
          K ⬅ L ⬅ S     <-- devel

where (as you already noted) the contents (the tree) of commit S makes all the files come out the same as they would in commit M. But there's no back-link (parent arrow) from S to topic. It's not a merge at all, it's just taking all the changes from topic, squashing them into a single change, and adding that as an entirely independent commit.

Now, the other thing about git merge --squash is that it does not make the final commit. So you could create the .git files that git would on a "regular" merge, and do a commit that has the two parents you'd get on a "real" merge. And then you'd get ... exactly what you get if you run git merge topic, a commit (label it S or M, it does not matter) that has the same tree again, but now has two parent-arrows, pointing to L and J, just like M.

In fact, running git merge --squash is almost exactly the same as running git merge --no-commit, except for the tracing files left behind when the merge is done (git commit uses some of these to set up the parents). The squash version does not write to .git/MERGE, .git/MERGE_HEAD, and .git/MERGE_MODE. (It does create .git/MERGE_MSG, the same as git merge --no-commit, and it also creates .git/SQUASH_MSG.)

So, basically, you have your choice: a real merge (two or more parents on the final commit), or a squash (same tree-combining mechanisms, but only one parent on the final commit). And, since git branch --merged works by looking at the "parent arrows" of each commit stored in the repository, only a real merge is really a merge, so only a real merge can be discovered later by git branch.

Saturday, September 18, 2021
 
air
answered 3 Months ago
air
49

There are two excellent Stack Overflow responses which address this problem:

How do I tell git to always select my local version for conflicted merges on a specific file?

and

.gitattributes & individual merge strategy for a file

I'd suggest reading through the top answer in the first link. It's long, but very detailed and informative.

Saturday, October 9, 2021
 
asator
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share